home *** CD-ROM | disk | FTP | other *** search
/ The Epic Collection 3 / Epic Collection 3, The (1997)(Epic Marketing)[!].iso / useful_tools / tolleuhr / source / tolleuhr.c < prev    next >
C/C++ Source or Header  |  1996-03-21  |  81KB  |  2,760 lines

  1. #define VERSION "1.5 (20.3.96)"
  2. /***************************************************************************
  3. *                                  *                                       *
  4. * Programm: TolleUhr               * Version: s.o.                         *
  5. *                                  *                                       *
  6. ****************************************************************************
  7. *                                                                          *
  8. * Dieses Programm ist Public-Domain, d.h. wer immer Lust dazu hat, darf    *
  9. * dieses Programm kopieren, umschreiben, usw., vorausgesetzt:              *
  10. *                                                                          *
  11. * 1. Die Autorenliste bleibt voll erhalten. (auch in About-Requestern)     *
  12. * 2. Wer etwas am Programm verbricht, muß sich auch dazuschreiben.         *
  13. *                                                                          *
  14. * Es wird keine Haftung für Schäden irgendwelcher Art übernommen.          *
  15. *                                                                          *
  16. * Autoren: Matthias Fleischer  Adlerstraße 30 7302 Ostfildern 2            *
  17. *          (fleischr@izfm.uni-stuttgart.de)                                *
  18. *          .                                                               *
  19. *          .(Auf Paul, schaff was !)                                       *
  20. *                                                                          *
  21. *          Gunther Nikl  Ziegendorfer Chaussee 96 19370 Parchim            *
  22. *          (gnikl@informatik.uni-rostock.de)                               *
  23. *                                                                          *
  24. ***************************************************************************/
  25.  
  26. /***************************************************************************/
  27. /*                                                                         */
  28. /* includes                                                                */
  29. /*                                                                         */
  30. /***************************************************************************/
  31.  
  32. #include <exec/types.h>
  33.  
  34. #ifndef REG
  35. #define REG(x) asm(#x)
  36. #endif
  37. #ifndef CONST
  38. #define CONST const
  39. #endif
  40. #ifndef INLINE
  41. #define INLINE inline
  42. #endif
  43.  
  44. #include <dos/dos.h>
  45. #include <dos/rdargs.h>
  46. #include <dos/datetime.h>
  47. #include <exec/tasks.h>
  48. #include <exec/memory.h>
  49. #include <exec/execbase.h>
  50. #include <devices/audio.h>
  51. #include <devices/timer.h>
  52. #include <hardware/cia.h>
  53. #include <prefs/prefhdr.h>
  54. #include <prefs/wbpattern.h>
  55. #include <graphics/gfxmacros.h>
  56. #include <intuition/intuition.h>
  57. #include <intuition/gadgetclass.h>
  58. #include <libraries/screennotify.h>
  59. #include <datatypes/pictureclass.h>
  60. #include <libraries/gadtools.h>
  61. #include <workbench/startup.h>
  62. #include <workbench/workbench.h>
  63. #include <clib/alib_protos.h>
  64. #include <clib/macros.h>
  65.  
  66. /*
  67. ** structure definitions now!
  68. */
  69.  
  70. struct gInfo {
  71.   WORD  left,top,width,height;
  72.   UWORD textnr,kind;
  73. };
  74.  
  75. struct wInfo {
  76.   UWORD        idcmp,textnr,gadcnt;
  77.   struct gInfo gi[1];
  78. };
  79.  
  80. struct WinGad {
  81.   struct Window *Win;
  82.   struct Gadget *Gad;
  83. };
  84.  
  85. struct DateTimeInfo {
  86.   struct DateTime dat;
  87.   UBYTE           buf[34];
  88. };
  89.  
  90. struct BackFillInfo {
  91.   STRPTR               PictureName;
  92.   Object              *PictureObject;
  93.   struct BitMapHeader *BitMapHeader;
  94.   struct BitMap       *BitMap;
  95. };
  96.  
  97. /*
  98. **  sizeof(struct Globals) _MUST_ be a multiple of 4!
  99. */
  100.  
  101. struct Globals {
  102.  
  103.   /*** library stuff ***/
  104.  
  105.   struct ExecBase      *SysBase;
  106.   struct DosLibrary    *DOSBase;
  107.   struct IntuitionBase *IntuitionBase;
  108.   struct GfxBase       *GfxBase;
  109.   struct Library       *GadtoolsBase,
  110.                        *IconBase,
  111.                        *DataTypesBase;
  112.   struct LocaleBase    *LocaleBase;
  113.   struct Catalog       *Catalog;
  114.  
  115.   /*** misc stuff ***/
  116.  
  117.   STRPTR                NameBuf,
  118.                         PubName;
  119.   BPTR                  OldLock;
  120.   LONG                  OldPri;
  121.  
  122.   /*** device stuff ***/
  123.  
  124.   struct MsgPort       *WindowPort;
  125.   struct MsgPort       *TimerPort;
  126.   struct timerequest   *TimerIO;
  127.   struct MsgPort       *AudioPort;
  128.   struct IOAudio       *AudioIO[2];
  129.   APTR                  WaveForm;
  130.  
  131.   /*** graphic stuff ***/
  132.  
  133.   APTR                  VisualInfo;
  134.   struct Menu          *Menus;
  135.   struct Window        *MainWin;
  136.   struct RastPort      *RPort1;
  137.   struct WinGad         ColorWin,
  138.                         AlarmWin;
  139.   struct Window        *AboutReq;
  140.  
  141.   /*** screen notify ***/
  142.  
  143.   struct Library       *ScreenNotifyBase;
  144.   struct MsgPort       *NotifyPort;
  145.   APTR                  NotifyHandle;
  146.  
  147.   /*** common variables ***/
  148.  
  149.   LONG                  Left,
  150.                         Top,
  151.                         Width,
  152.                         Height,
  153.                         BoLeft,
  154.                         BoTop,
  155.                         Width2,
  156.                         Height2,
  157.                         ReDrawx1,
  158.                         ReDrawy1,
  159.                         ReDrawx2,
  160.                         ReDrawy2,
  161.                         xMask,
  162.                         yMask;
  163.   PLANEPTR              Buf;
  164.   UWORD                *PlayTune;
  165.   UBYTE                *Color;
  166.   LONG                  Std,
  167.                         Min,
  168.                         Sec,
  169.                         AlStd,
  170.                         AlMin,
  171.                         St,
  172.                         Mi,
  173.                         xOffset,
  174.                         yOffset;
  175.   WORD                  GadSize;
  176.   UWORD                 ImgType;
  177.  
  178.   /*** flags ***/
  179.  
  180.   BYTE                  TimerOpen,
  181.                         TimerSent,
  182.                         AudioOpen,
  183.                         AudioSent[2],
  184.                         SoundOn,
  185.                         xDouble,
  186.                         yDouble,
  187.                         ChangedDir,
  188.                         ChangedPri,
  189.                         Active,
  190.                         Alarm,
  191.                         Filter,
  192.                         HiRes,
  193.                         Interlace,
  194.                         SmartHour,
  195.                         EndAll,
  196.                         CloseGad,
  197.                         Backdrop,
  198.                         Fixed,
  199.                         UseImage;
  200.   UBYTE                 Seconds,
  201.                         Oval,
  202.                         Show,
  203.                         HandType,
  204.                         HandWidth,
  205.                         Shadow,
  206.                         BorderCount,
  207.                         Chime,
  208.                         NoRemap,
  209.                         RequestNr,
  210.                         ScrNotify;
  211.  
  212.   /*** structures ***/
  213.  
  214.   struct BackFillInfo   BFInfo;
  215.   struct WBArg          ProgArg;
  216.   UBYTE                 Pens[16],
  217.                         Must[4];
  218.   struct NewWindow      NewWindowBuf;
  219.   struct Gadget         GadgetBuf[4];
  220.   struct RastPort       RPort2;
  221.   struct BitMap         BitMap1;
  222.   struct TmpRas         TempRas;
  223.   struct AreaInfo       AreaInfo;
  224.   UWORD                 Table[14],
  225.                         Muster[8][2];
  226.   struct NewGadget      NewGad;
  227.   UWORD                 wPad;
  228.   struct EasyStruct     EasyBuf;
  229.   struct DateTimeInfo   DateTime;
  230. };
  231.  
  232. #define PUB_SCREEN (gb->NewWindowBuf.Screen)
  233.  
  234. /*
  235. ** ptr to the `global' data space (will be on the stack 8)
  236. */
  237.  
  238. REGISTER struct Globals *gb REG(a4);
  239.  
  240. /*
  241. ** redirect library bases to the `global' data space
  242. */
  243.  
  244. #define BASE_NAME gb->ScreenNotifyBase
  245. #include <proto/screennotify.h>
  246. #undef BASE_NAME
  247.  
  248. #define BASE_NAME gb->LocaleBase
  249. #include <proto/locale.h>
  250. #undef BASE_NAME
  251.  
  252. #define BASE_NAME gb->DataTypesBase
  253. #include <proto/datatypes.h>
  254. #undef BASE_NAME
  255.  
  256. #define BASE_NAME gb->IntuitionBase
  257. #include <proto/intuition.h>
  258. #undef BASE_NAME
  259.  
  260. #define BASE_NAME gb->GadtoolsBase
  261. #include <proto/gadtools.h>
  262. #undef BASE_NAME
  263.  
  264. #define BASE_NAME gb->GfxBase
  265. #include <proto/graphics.h>
  266. #undef BASE_NAME
  267.  
  268. #define BASE_NAME gb->IconBase
  269. #include <proto/icon.h>
  270. #undef BASE_NAME
  271.  
  272. #define BASE_NAME gb->SysBase
  273. #include <proto/exec.h>
  274. #undef BASE_NAME
  275.  
  276. #define BASE_NAME gb->DOSBase
  277. #include <proto/dos.h>
  278. #undef BASE_NAME
  279.  
  280. #include <proto/iffparse.h>
  281. #include <proto/alib.h>
  282.  
  283. /*
  284. ** strcpy() && strlen()
  285. */
  286.  
  287. #include <string.h>
  288.  
  289. /*
  290. ** locale string numbers
  291. */
  292.  
  293. #include "tolleuhr_locale.h"
  294.  
  295. /***************************************************************************/
  296. /*                                                                         */
  297. /* prototypes                                                              */
  298. /*                                                                         */
  299. /***************************************************************************/
  300.  
  301. VOID AddScreenNotify();
  302. LONG OpenMainWindow();
  303. VOID LoadImage();
  304. LONG MakeMenus();
  305. LONG InitClock();
  306. LONG GetArguments(struct WBStartup *);
  307. VOID MergeToolTypes();
  308. VOID ParseArgs(STRPTR,LONG);
  309. VOID ReadStr(UBYTE *,UBYTE *,UBYTE *,LONG);
  310. LONG XtoD(LONG);
  311. LONG OpenDevs();
  312. LONG OpenLibs();
  313. VOID Main();
  314. VOID CloseLibs();
  315. VOID CloseDevs();
  316. VOID NewSize1();
  317. VOID CloseAboutReq();
  318. VOID CloseGfx();
  319. VOID FreeWindow(struct WinGad *);
  320. VOID CloseWindowSafely(struct Window *);
  321. VOID RemScreenNotify();
  322. LONG CheckNotify();
  323. VOID CheckAboutReq();
  324. VOID CheckWindows();
  325. VOID HandleMenus(ULONG);
  326. LONG NewSize2();
  327. VOID NewTitle();
  328. ULONG NextTick();
  329. VOID Rahmen();
  330. VOID ZifferBlatt();
  331. VOID Zeiger(ULONG,LONG,LONG,LONG,LONG);
  332. VOID Zeichnen();
  333. VOID SetPattern();
  334. VOID SaveSettings();
  335. STRPTR SetToolType(STRPTR,STRPTR,LONG,...);
  336. STRPTR GetToolType(LONG);
  337. STRPTR SetStr(STRPTR,STRPTR,LONG);
  338. LONG DtoX(LONG);
  339. VOID TestIfAlarm();
  340. VOID StartTune(CONST UWORD *);
  341. VOID PlayNote();
  342. VOID EndTune();
  343. VOID CreateRequest(struct WinGad *,struct wInfo *,struct TagItem **);
  344. struct Window *OpenWindowShared(struct NewWindow *,CONST struct TagItem *,ULONG);
  345. STRPTR GetCatalogString(LONG);
  346. VOID CopyTiledBitMap(struct BitMap *,LONG,LONG,struct BitMap *,LONG,LONG);
  347.  
  348. /*
  349. ** replacements
  350. */
  351.  
  352. LONG blt_bitmap(struct BitMap *,LONG,LONG,struct BitMap *,LONG,LONG,LONG,LONG,ULONG,ULONG,PLANEPTR);
  353. Object *new_dt_object(APTR name,ULONG,...);
  354. ULONG get_dt_attrs(Object *,ULONG,...);
  355.  
  356. /***************************************************************************/
  357. /*                                                                         */
  358. /* `global' defines                                                        */
  359. /*                                                                         */
  360. /***************************************************************************/
  361.  
  362. #define ciaa (*((struct CIA *)0xbfe001L))
  363.  
  364. #define GB_GADCOUNT (sizeof(gb->GadgetBuf)/sizeof(struct Gadget))
  365.  
  366. enum {WT_CLOSEGAD=1,WT_BACKDROP=2,WT_FIXED=4,WT_USEIMAGE=8,WT_LAST=16};
  367.  
  368. /***************************************************************************/
  369. /*                                                                         */
  370. /* memory clear function (!!! caution: size _MUST_ be a multiple of 4 !!!) */
  371. /*                                                                         */
  372. /***************************************************************************/
  373.  
  374. STATIC INLINE VOID MEMZEROL(VOID *mem,ULONG size)
  375. { ULONG *p;
  376.   WORD s;
  377.  
  378.   for(p=(ULONG *)mem,s=(size/sizeof(ULONG))-1; s>=0; *p++=0,s--);
  379. }
  380.  
  381. /***************************************************************************/
  382. /*                                                                         */
  383. /* implementation                                                          */
  384. /*                                                                         */
  385. /***************************************************************************/
  386.  
  387. LONG Start()
  388. { struct Globals globals;
  389.  
  390.   MEMZEROL(&globals,sizeof(struct Globals)); gb = &globals;
  391.  
  392.   gb->SysBase = *(struct ExecBase **)4L;
  393.  
  394.   Main();
  395.  
  396.   return 0;
  397. }
  398.  
  399. /***************************************************************************/
  400. /*                                                                         */
  401. /* version string                                                          */
  402. /*                                                                         */
  403. /***************************************************************************/
  404.  
  405. CONST UBYTE Version[] = "$VER: TolleUhr "VERSION" by M.Fleischer and G.Nikl in 1993/96";
  406.  
  407. #define PROGNAME ((UBYTE *)(&Version[6]))
  408.  
  409. /***************************************************************************/
  410. /*                                                                         */
  411. /* install screen notification (if desired and possible)                   */
  412. /*                                                                         */
  413. /***************************************************************************/
  414.  
  415. VOID AddScreenNotify()
  416. { struct PubScreenNode *pubnode;
  417.  
  418.   if ((pubnode=(struct PubScreenNode *)FindName(LockPubScreenList(),"Workbench")) != NULL)
  419.     if (pubnode->psn_Screen != PUB_SCREEN)
  420.       pubnode=NULL;
  421.   UnlockPubScreenList();
  422.  
  423.   if (pubnode != NULL)
  424.     if ((gb->ScreenNotifyBase=OpenLibrary(SCREENNOTIFY_NAME,0)) != NULL)
  425.     {
  426.       if ((gb->NotifyPort=CreateMsgPort()) != NULL)
  427.         if ((gb->NotifyHandle=AddWorkbenchClient(gb->NotifyPort,0)) != NULL)
  428.           return;
  429.       RemScreenNotify();
  430.     }
  431. }
  432.  
  433. /***************************************************************************/
  434. /*                                                                         */
  435. /* open clock window                                                       */
  436. /*                                                                         */
  437. /***************************************************************************/
  438.  
  439. #define MAINIDCMP (IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK | \
  440.                    IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW)
  441.  
  442. CONST struct TagItem WindowTags[] = {
  443.   { WA_InnerWidth , 148 },
  444.   { WA_InnerHeight,  72 },
  445.   { WA_AutoAdjust ,TRUE },
  446.   { TAG_DONE      ,NULL }
  447. };
  448.  
  449. LONG OpenMainWindow()
  450. { struct NewWindow *nw;
  451.   struct Window *win;
  452.   ULONG mnum;
  453.   LONG ret;
  454.  
  455.   nw = &gb->NewWindowBuf;
  456.  
  457.   nw->LeftEdge    = gb->Left;
  458.   nw->TopEdge     = gb->Top;
  459.   nw->Width       = gb->Width;
  460.   nw->Height      = gb->Height;
  461.   nw->BlockPen    = 1;
  462.   nw->Flags       = WFLG_SIMPLE_REFRESH | WFLG_BORDERLESS | WFLG_NEWLOOKMENUS |
  463.                     (gb->Backdrop ? WFLG_BACKDROP : 0);
  464.   nw->FirstGadget = &gb->GadgetBuf[0];
  465.   nw->Title       = NULL;
  466.   nw->MinWidth    = 10;
  467.   nw->MinHeight   = 10;
  468.   nw->MaxWidth    = 65535;
  469.   nw->MaxHeight   = 65535;
  470.   nw->Type        = PUBLICSCREEN;
  471.  
  472.   ret = 0;
  473.  
  474.   if ((gb->MainWin=(win=OpenWindowShared(nw,&WindowTags[2],MAINIDCMP))) != NULL)
  475.   {
  476.     PUB_SCREEN = win->WScreen;
  477.     gb->RPort1 = win->RPort;
  478.     SetMenuStrip(win,gb->Menus);
  479.     if (!gb->BFInfo.BitMap)
  480.       OffMenu(win,FULLMENUNUM(1,8,3));
  481.     SetAPen(gb->RPort1,gb->Pens[0]);
  482.     if (!NewSize2())
  483.     {
  484.       NextTick();
  485.       NewTitle();
  486.       Rahmen();
  487.       ZifferBlatt();
  488.       Zeichnen();
  489.       ret = 1;
  490.     }
  491.   }
  492.  
  493.   return ret;
  494. }
  495.  
  496. /***************************************************************************/
  497. /*                                                                         */
  498. /* load background image via datatypes                                     */
  499. /*                                                                         */
  500. /***************************************************************************/
  501.  
  502. CONST struct TagItem PicTags[] = {
  503.   { DTA_GroupID          ,GID_PICTURE     },
  504.   { PDTA_FreeSourceBitMap,TRUE            },
  505.   { OBP_Precision        ,PRECISION_IMAGE },
  506.   { TAG_DONE             ,NULL            }
  507. };
  508.  
  509. CONST ULONG PicMsg[] = {
  510.   DTM_PROCLAYOUT,NULL,1
  511. };
  512.  
  513. VOID LoadImage()
  514. { struct Library *IFFParseBase;
  515.   struct WBPatternPrefs pat;
  516.   struct IFFHandle *handle;
  517.   STRPTR name;
  518.   Object *obj;
  519.   LONG len;
  520.  
  521.   if ((name=gb->BFInfo.PictureName) == NULL)
  522.   {
  523.     if ((IFFParseBase=OpenLibrary("iffparse.library",37L)) != NULL)
  524.     {
  525.       if ((handle=AllocIFF()) != NULL)
  526.       {
  527.         if ((handle->iff_Stream=(ULONG)Open("env:sys/wbpattern.prefs",MODE_OLDFILE)) != NULL)
  528.         {
  529.           InitIFFasDOS(handle);
  530.  
  531.           if (!OpenIFF(handle,IFFF_READ))
  532.           {
  533.             if (!StopChunk(handle,ID_PREF,ID_PTRN))
  534.             {
  535.               while(!ParseIFF(handle,IFFPARSE_SCAN))
  536.               {
  537.                 if (ReadChunkBytes(handle,&pat,sizeof(struct WBPatternPrefs)) != sizeof(struct WBPatternPrefs))
  538.                   break;
  539.  
  540.                 if (pat.wbp_Which == gb->ImgType && !pat.wbp_Flags)
  541.                 {
  542.                   if ((gb->BFInfo.PictureName=AllocVec(1+(len=pat.wbp_DataLength),MEMF_CLEAR|MEMF_ANY)) != NULL)
  543.                   {
  544.                     ReadChunkBytes(handle,gb->BFInfo.PictureName,len);
  545.                   }
  546.                   break;
  547.                 }
  548.               }
  549.             }
  550.             CloseIFF(handle);
  551.           }
  552.           Close((BPTR)handle->iff_Stream);
  553.         }
  554.         FreeIFF(handle);
  555.       }
  556.       CloseLibrary(IFFParseBase);
  557.     }
  558.     name=gb->BFInfo.PictureName;
  559.   }
  560.  
  561.   if (name != NULL)
  562.   {
  563.     gb->BFInfo.PictureObject = obj =
  564.       new_dt_object(name,
  565.                     PDTA_Screen,PUB_SCREEN,
  566.                     PDTA_Remap ,(gb->NoRemap ? FALSE : TRUE),
  567.                     TAG_MORE   ,PicTags);
  568.     if (obj != NULL)
  569.       if (DoDTMethodA(obj,NULL,NULL,(Msg)&PicMsg))
  570.         get_dt_attrs(obj,
  571.                      PDTA_BitMapHeader,&gb->BFInfo.BitMapHeader,
  572.                      PDTA_DestBitMap  ,&gb->BFInfo.BitMap,
  573.                      TAG_DONE);
  574.   }
  575. }
  576.  
  577. /***************************************************************************/
  578. /*                                                                         */
  579. /* create gadgets and menus                                                */
  580. /*                                                                         */
  581. /***************************************************************************/
  582.  
  583. CONST UBYTE gadgetInfo[] = {
  584.   GADGHNONE|GRELRIGHT           ,GTYP_WDEPTH,
  585.   GADGHNONE|GRELRIGHT|GRELBOTTOM,GTYP_SIZING,
  586.   GADGHNONE|GRELWIDTH|GRELHEIGHT,GTYP_WDRAGGING,
  587.   GADGHNONE                     ,GTYP_CLOSE
  588. };
  589.  
  590. enum {
  591.   MENU_PROJECT=0,
  592.    MENU_PROJECT_ABOUT,
  593.    MENU_PROJECT_QUIT,
  594.   MENU_SETTINGS,
  595.    MENU_SETTINGS_SECONDS,
  596.    MENU_SETTINGS_OVAL,
  597.    MENU_SETTINGS_SHOW,
  598.     MENU_SETTINGS_SHOW_MINUTES,
  599.     MENU_SETTINGS_SHOW_HOURS,
  600.     MENU_SETTINGS_SHOW_QUARTER,
  601.     MENU_SETTINGS_SHOW_ONE,
  602.     MENU_SETTINGS_SHOW_NONE,
  603.    MENU_SETTINGS_HANDS,
  604.     MENU_SETTINGS_HANDS_LINE,
  605.     MENU_SETTINGS_HANDS_TRIANGLE,
  606.     MENU_SETTINGS_HANDS_RHOMBUS,
  607.     MENU_SETTINGS_HANDS_RECTANGLE,
  608.     MENU_SETTINGS_HANDS_BARLABEL,
  609.     MENU_SETTINGS_HANDS_VERYTHIN,
  610.     MENU_SETTINGS_HANDS_THIN,
  611.     MENU_SETTINGS_HANDS_NORMAL,
  612.     MENU_SETTINGS_HANDS_THICK,
  613.     MENU_SETTINGS_HANDS_VERYTHICK,
  614.    MENU_SETTINGS_SHADOW,
  615.    MENU_SETTINGS_BORDER,
  616.     MENU_SETTINGS_BORDER_NONE,
  617.     MENU_SETTINGS_BORDER_SINGLE,
  618.     MENU_SETTINGS_BORDER_DOUBLE,
  619.     MENU_SETTINGS_BORDER_BARLABEL,
  620.     MENU_SETTINGS_BORDER_HIRES,
  621.     MENU_SETTINGS_BORDER_INTERLACE,
  622.    MENU_SETTINGS_CHIME,
  623.     MENU_SETTINGS_CHIME_NONE,
  624.     MENU_SETTINGS_CHIME_HOURS,
  625.     MENU_SETTINGS_CHIME_QUARTER,
  626.     MENU_SETTINGS_CHIME_BARLABEL,
  627.     MENU_SETTINGS_CHIME_SMART,
  628.    MENU_SETTINGS_ALARM,
  629.     MENU_SETTINGS_ALARM_SET,
  630.     MENU_SETTINGS_ALARM_ON,
  631.    MENU_SETTINGS_WINDOW,
  632.     MENU_SETTINGS_WINDOW_CLOSEGAD,
  633.     MENU_SETTINGS_WINDOW_BACKDROP,
  634.     MENU_SETTINGS_WINDOW_FIXED,
  635.     MENU_SETTINGS_WINDOW_USEIMAGE,
  636.    MENU_SETTINGS_BARLABEL,
  637.    MENU_SETTINGS_SAVE,
  638.   MENU_COLORS,
  639.    MENU_COLORS_SECONDS,
  640.    MENU_COLORS_MINAPEN,
  641.    MENU_COLORS_MINOPEN,
  642.    MENU_COLORS_HOURAPEN,
  643.    MENU_COLORS_HOUROPEN,
  644.    MENU_COLORS_SHADOW,
  645.    MENU_COLORS_STR12,
  646.    MENU_COLORS_QUARTER,
  647.    MENU_COLORS_HOURS,
  648.    MENU_COLORS_MINUTES,
  649.    MENU_COLORS_BORDER0,
  650.    MENU_COLORS_BORDER1,
  651.    MENU_COLORS_BORDER2,
  652.    MENU_COLORS_BORDER3,
  653.   MENU_PATTERN,
  654.    MENU_PATTERN_COLOR0,
  655.    MENU_PATTERN_COLOR1,
  656.    MENU_PATTERN_COLOR2,
  657.    MENU_PATTERN_COLOR3
  658. };
  659.  
  660. CONST UBYTE MenuInfo[] = {
  661.   NM_TITLE,MSG_PROJECT,0,0,
  662.    NM_ITEM,MSG_ABOUT,0,0,
  663.    NM_ITEM,MSG_QUIT,0,0,
  664.   NM_TITLE,MSG_SETTINGS,0,0,
  665.    NM_ITEM,MSG_SECONDS,CHECKIT|MENUTOGGLE,0,
  666.    NM_ITEM,MSG_OVAL,CHECKIT|MENUTOGGLE,0,
  667.    NM_ITEM,MSG_SHOW,0,0,
  668.     NM_SUB,MSG_MINUTES,CHECKIT,2|4|8|16,
  669.     NM_SUB,MSG_HOURS,CHECKIT,1|4|8|16,
  670.     NM_SUB,MSG_QUARTER,CHECKIT,1|2|8|16,
  671.     NM_SUB,MSG_ONE,CHECKIT,1|2|4|16,
  672.     NM_SUB,MSG_NONE,CHECKIT,1|2|4|8,
  673.    NM_ITEM,MSG_HANDS,0,0,
  674.     NM_SUB,MSG_LINE,CHECKIT,2|4|8,
  675.     NM_SUB,MSG_TRIANGLE,CHECKIT,1|4|8,
  676.     NM_SUB,MSG_RHOMBUS,CHECKIT,1|2|8,
  677.     NM_SUB,MSG_RECTANGLE,CHECKIT,1|2|4,
  678.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  679.     NM_SUB,MSG_VERYTHIN,CHECKIT,128+(2|4|8|16),
  680.     NM_SUB,MSG_THIN,CHECKIT,128+(1|4|8|16),
  681.     NM_SUB,MSG_NORMAL,CHECKIT,128+(1|2|8|16),
  682.     NM_SUB,MSG_THICK,CHECKIT,128+(1|2|4|16),
  683.     NM_SUB,MSG_VERYTHICK,CHECKIT,128+(1|2|4|8),
  684.    NM_ITEM,MSG_SHADOW,CHECKIT|MENUTOGGLE,0,
  685.    NM_ITEM,MSG_BORDER,0,0,
  686.     NM_SUB,MSG_NONE,CHECKIT,2|4,
  687.     NM_SUB,MSG_SINGLE,CHECKIT,1|4,
  688.     NM_SUB,MSG_DOUBLE,CHECKIT,1|2,
  689.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  690.     NM_SUB,MSG_HIRES,CHECKIT|MENUTOGGLE,0,
  691.     NM_SUB,MSG_INTERLACE,CHECKIT|MENUTOGGLE,0,
  692.    NM_ITEM,MSG_CHIME,0,0,
  693.     NM_SUB,MSG_NONE,CHECKIT,2|4,
  694.     NM_SUB,MSG_HOURS,CHECKIT,1|4,
  695.     NM_SUB,MSG_QUARTER,CHECKIT,1|2,
  696.     NM_SUB,(UBYTE)NM_BARLABEL,0,0,
  697.     NM_SUB,MSG_SMART,CHECKIT|MENUTOGGLE,0,
  698.    NM_ITEM,MSG_ALARM,0,0,
  699.     NM_SUB,MSG_SET,0,0,
  700.     NM_SUB,MSG_ON,CHECKIT|MENUTOGGLE,0,
  701.    NM_ITEM,MSG_WINDOW,0,0,
  702.     NM_SUB,MSG_CLOSEGAD,CHECKIT|MENUTOGGLE,0,
  703.     NM_SUB,MSG_BACKDROP,CHECKIT|MENUTOGGLE,0,
  704.     NM_SUB,MSG_FIXED,CHECKIT|MENUTOGGLE,0,
  705.     NM_SUB,MSG_USEIMAGE,CHECKIT|MENUTOGGLE,0,
  706.    NM_ITEM,(UBYTE)NM_BARLABEL,0,0,
  707.    NM_ITEM,MSG_SAVESETTINGS,0,0,
  708.   NM_TITLE,MSG_COLORS,0,0,
  709.    NM_ITEM,MSG_SECONDS,0,0,
  710.    NM_ITEM,MSG_MINAPEN,0,0,
  711.    NM_ITEM,MSG_MINOPEN,0,0,
  712.    NM_ITEM,MSG_HOURAPEN,0,0,
  713.    NM_ITEM,MSG_HOUROPEN,0,0,
  714.    NM_ITEM,MSG_SHADOW,0,0,
  715.    NM_ITEM,MSG_STR12,0,0,
  716.    NM_ITEM,MSG_QUARTER,0,0,
  717.    NM_ITEM,MSG_HOURS,0,0,
  718.    NM_ITEM,MSG_MINUTES,0,0,
  719.    NM_ITEM,MSG_BORDER0,0,0,
  720.    NM_ITEM,MSG_BORDER1,0,0,
  721.    NM_ITEM,MSG_BORDER2,0,0,
  722.    NM_ITEM,MSG_BORDER3,0,0,
  723.   NM_TITLE,MSG_PATTERN,0,0,
  724.    NM_ITEM,MSG_COLOR0,0,0,
  725.    NM_ITEM,MSG_COLOR1,0,0,
  726.    NM_ITEM,MSG_COLOR2,0,0,
  727.    NM_ITEM,MSG_COLOR3,0,0
  728. };
  729.  
  730. #define NM_ITEMCOUNT (sizeof(MenuInfo)/(4*sizeof(UBYTE)))
  731.  
  732. CONST struct TagItem MenuTags[] = {
  733.   { GTMN_NewLookMenus,TRUE },
  734.   { TAG_DONE         ,NULL }
  735. };
  736.  
  737. LONG MakeMenus()
  738. { struct NewMenu menubuf[NM_ITEMCOUNT+1],*nm;
  739.   struct Gadget *gad;
  740.   CONST UBYTE *p;
  741.   LONG tmp,index,ret;
  742.   WORD i,num;
  743.  
  744.   for(gad=&gb->GadgetBuf[0],p=&gadgetInfo[0],num=1,i=GB_GADCOUNT-1; i>=0; i--)
  745.   { gad->Width      = num;
  746.     gad->Height     = num;
  747.     gad->Flags      = *p++;
  748.     gad->Activation = num; /* GACT_RELVERIFY */
  749.     gad->GadgetType = *p++;
  750.     gad++;
  751.     gad[-1].NextGadget = gad;
  752.   }
  753.   gad[-1].NextGadget = NULL; gb->GadSize = 0;
  754.  
  755.   MEMZEROL(&menubuf[0],sizeof(menubuf));
  756.   for(nm=&menubuf[0],p=&MenuInfo[0],i=NM_ITEMCOUNT-1; i>=0; i--)
  757.   { nm->nm_Type          = *p++;
  758.     if ((tmp=(BYTE)*p++) >= 0) tmp=(LONG)GetCatalogString(tmp);
  759.     nm->nm_Label         = (STRPTR)tmp;
  760.     nm->nm_Flags         = (UWORD)*p++;
  761.     if ((num=(BYTE)*p++) < 0) num=(((num&0x7f))<<5);
  762.     nm->nm_MutualExclude = (ULONG)num;
  763.     nm++;
  764.   }
  765.   menubuf[MENU_PROJECT_ABOUT].nm_CommKey = GetCatalogString(MSG_ABOUTKEY);
  766.   menubuf[MENU_PROJECT_QUIT ].nm_CommKey = GetCatalogString(MSG_QUITKEY);
  767.   menubuf[MENU_SETTINGS_SAVE].nm_CommKey = GetCatalogString(MSG_SAVEKEY);
  768.  
  769.   ret = 0;
  770.  
  771.   if ((gb->VisualInfo=GetVisualInfoA(PUB_SCREEN,NULL)) != NULL)
  772.   {
  773.     nm = &menubuf[0]; i = CHECKED;
  774.     nm[MENU_SETTINGS_SECONDS].nm_Flags
  775.      |= i & (gb->Seconds ? -1 : 0);
  776.     nm[MENU_SETTINGS_OVAL].nm_Flags
  777.      |= i & (gb->Oval ? -1 : 0);
  778.     index = MENU_SETTINGS_SHOW+gb->Show+1;
  779.     nm[index].nm_Flags
  780.      |= i;
  781.     index = MENU_SETTINGS_HANDS+gb->HandType+1;
  782.     nm[index].nm_Flags
  783.      |= i;
  784.     index = MENU_SETTINGS_HANDS+gb->HandWidth+6;
  785.     nm[index].nm_Flags
  786.      |= i;
  787.     nm[MENU_SETTINGS_SHADOW].nm_Flags
  788.      |= i & (gb->Shadow ? -1 : 0);
  789.     index = MENU_SETTINGS_BORDER+gb->BorderCount+1;
  790.     nm[index].nm_Flags
  791.      |= i;
  792.     nm[MENU_SETTINGS_BORDER_HIRES].nm_Flags
  793.      |= i & (gb->HiRes ? -1 : 0);
  794.     nm[MENU_SETTINGS_BORDER_INTERLACE].nm_Flags
  795.      |= i & (gb->Interlace ? -1 : 0);
  796.     index = MENU_SETTINGS_CHIME+gb->Chime+1;
  797.     nm[index].nm_Flags
  798.      |= i;
  799.     nm[MENU_SETTINGS_CHIME_SMART].nm_Flags
  800.      |= i & (gb->SmartHour ? -1 : 0);
  801.  
  802.     nm[MENU_SETTINGS_WINDOW_CLOSEGAD].nm_Flags
  803.      |= i & (gb->CloseGad ? -1 : 0);
  804.     nm[MENU_SETTINGS_WINDOW_BACKDROP].nm_Flags
  805.      |= i & (gb->Backdrop ? -1 : 0);
  806.     nm[MENU_SETTINGS_WINDOW_FIXED].nm_Flags
  807.      |= i & (gb->Fixed ? -1 : 0);
  808.     nm[MENU_SETTINGS_WINDOW_USEIMAGE].nm_Flags
  809.      |= i & (gb->BFInfo.BitMap && gb->UseImage ? -1 : 0);
  810.  
  811.     if ((gb->Menus=CreateMenusA(&menubuf[0],NULL)) != NULL)
  812.       ret=LayoutMenusA(gb->Menus,gb->VisualInfo,(struct TagItem *)MenuTags);
  813.   }
  814.  
  815.   return ret;
  816. }
  817.  
  818. /***************************************************************************/
  819. /*                                                                         */
  820. /* initialize all graphics                                                 */
  821. /*                                                                         */
  822. /***************************************************************************/
  823.  
  824. LONG InitClock()
  825. { struct Screen *scr;
  826.   LONG ret;
  827.  
  828.   if ((scr=LockPubScreen(gb->PubName)) == NULL)
  829.     scr=LockPubScreen(NULL);
  830.  
  831.   ret = 0;
  832.  
  833.   if ((PUB_SCREEN=scr) != NULL)
  834.   {
  835.     if (gb->DataTypesBase)
  836.       LoadImage();
  837.     SetPattern();
  838.     if (MakeMenus())
  839.       ret = OpenMainWindow();
  840.     UnlockPubScreen(NULL,scr);
  841.   }
  842.  
  843.   return ret;
  844. }
  845.  
  846. /***************************************************************************/
  847. /*                                                                         */
  848. /* get arguments either from CLI or WB                                     */
  849. /*                                                                         */
  850. /***************************************************************************/
  851.  
  852. LONG GetArguments(struct WBStartup *wm)
  853. { struct WBArg *arg;
  854.   STRPTR buf;
  855.  
  856.   if (wm != NULL)
  857.   {
  858.     arg = wm->sm_ArgList;
  859.     if (wm->sm_NumArgs>1)
  860.       arg++;
  861.     gb->ProgArg.wa_Lock = arg->wa_Lock;
  862.     gb->ProgArg.wa_Name = arg->wa_Name;
  863.     gb->OldLock = CurrentDir(arg->wa_Lock);
  864.     gb->ChangedDir = -1;
  865.     MergeToolTypes();
  866.   }
  867.   else
  868.     if ((gb->NameBuf=(buf=AllocVec(124,MEMF_ANY))) != NULL)
  869.     {
  870.       gb->ProgArg.wa_Lock = GetProgramDir();
  871.       GetProgramName(buf,124);
  872.       gb->ProgArg.wa_Name = FilePart(buf);
  873.       ParseArgs(NULL,0);
  874.     }
  875.     else
  876.       return 0;
  877.  
  878.   return 1;
  879. }
  880.  
  881. /*
  882. ** read all tooltypes
  883. */
  884.  
  885. STATIC INLINE STRPTR stpcpy(STRPTR dst,STRPTR src)
  886. {
  887.   while((*dst++=*src++)); return(dst-1);
  888. }
  889.  
  890. VOID MergeToolTypes()
  891. { struct DiskObject *dobj;
  892.   STRPTR argstr,string,p;
  893.   LONG arglen,strln;
  894.   BPTR old_cd;
  895.   char **tt;
  896.  
  897.   argstr = (STRPTR)&gb->EasyBuf; *argstr = '\n'; arglen = 1; string=NULL;
  898.  
  899.   old_cd = CurrentDir(gb->ProgArg.wa_Lock);
  900.  
  901.   if ((dobj=GetDiskObject(gb->ProgArg.wa_Name)) != NULL)
  902.   {
  903.     tt = dobj->do_ToolTypes; strln = 1;
  904.     while (*tt != NULL)
  905.     {
  906.       strln+=strlen(*tt++)+1;
  907.     }
  908.  
  909.     if ((string=AllocVec((strln+sizeof(ULONG)-1)&~(sizeof(ULONG)-1),MEMF_ANY)) != NULL)
  910.     {
  911.       tt = dobj->do_ToolTypes; p=string;
  912.       while (*tt != NULL)
  913.       {
  914.         p=stpcpy(p,*tt++); *p++ = ' ';
  915.       }
  916.       *p = '\n';
  917.  
  918.       argstr = string; arglen = strln;
  919.     }
  920.  
  921.     FreeDiskObject(dobj);
  922.   }
  923.  
  924.   ParseArgs(argstr,arglen);
  925.  
  926.   if (string)
  927.     FreeVec(string);
  928.  
  929.   (VOID)CurrentDir(old_cd);
  930. }
  931.  
  932. /*
  933. ** parse arguments and set default values
  934. */
  935.  
  936. enum {
  937.   OPT_NULL=-1,OPT_TOP,OPT_LEFT,OPT_WIDTH,OPT_HEIGHT,OPT_SECONDS,OPT_PATTERN,
  938.   OPT_OVAL,OPT_SHADOW,OPT_SHOWFACE,OPT_HANDTYPE,OPT_HANDWIDTH,OPT_DRAWPENS,
  939.   OPT_BORDERTYPE,OPT_WINDOWTYPE,OPT_CHIME,OPT_SCRNOTIFY,OPT_WBIMAGE,
  940.   OPT_NOREMAP,OPT_IMAGE,OPT_PUBSCREEN,OPT_TASKPRI,OPT_SIZEOF
  941. };
  942.  
  943. #define TEMPLATE \
  944.   "/M,TOP/N,LEFT/N,WIDTH/N,HEIGHT/N,SECONDS/S,PATTERN/K,OVAL/S,SHADOW/S,"    \
  945.   "SHOWFACE/N,HANDTYPE/N,HANDWIDTH/N,DRAWPENS/K,BORDERTYPE/N,WINDOWTYPE/N,"  \
  946.   "CHIME/N,SCREENNOTIFY/S,WBIMAGE/S,NOREMAP/S,IMAGE/K,PUBSCREEN/K,TASKPRI/N"
  947.  
  948. CONST UBYTE Pens[] = {
  949.   2,0,2,0,2,1,2,2,2,2,0,1,2,3
  950. };
  951.  
  952. VOID ParseArgs(STRPTR argstr,LONG length)
  953. { struct RDArgs *rda,*args;
  954.   LONG result[OPT_SIZEOF+1],*res,def,tmp;
  955.   STRPTR tmpl;
  956.  
  957.   MEMZEROL(&result[0],sizeof(result)); args = NULL;
  958.  
  959.   if ((rda=AllocDosObject(DOS_RDARGS,NULL)) != NULL)
  960.   {
  961.     rda->RDA_Source.CS_Buffer = argstr;
  962.     rda->RDA_Source.CS_Length = length;
  963.     tmpl = TEMPLATE; res = &result[0];
  964.     if (rda->RDA_Source.CS_Buffer == NULL)
  965.     {
  966.       res++; tmpl+=3;
  967.     }
  968.     args = ReadArgs(tmpl,res,rda);
  969.   }
  970.  
  971.   res = &result[1];
  972.  
  973.   def = 50;
  974.   if (res[OPT_TOP])
  975.   {
  976.     tmp = *(LONG *)res[OPT_TOP]; if (tmp >= 0) def = tmp;
  977.   }
  978.   gb->Top = def;
  979.  
  980.   def = 50;
  981.   if (res[OPT_LEFT])
  982.   {
  983.     tmp = *(LONG *)res[OPT_LEFT]; if (tmp >= 0) def = tmp;
  984.   }
  985.   gb->Left = def;
  986.  
  987.   def = 108;
  988.   if (res[OPT_WIDTH])
  989.   {
  990.     tmp = *(LONG *)res[OPT_WIDTH]; if (tmp >= 10) def = tmp;
  991.   }
  992.   gb->Width = def;
  993.  
  994.   def = 54;
  995.   if (res[OPT_HEIGHT])
  996.   {
  997.     tmp = *(LONG *)res[OPT_HEIGHT]; if (tmp >= 10) def = tmp;
  998.   }
  999.   gb->Height = def;
  1000.  
  1001.   gb->Seconds = res[OPT_SECONDS];
  1002.  
  1003.   ReadStr(&gb->Must[0],(STRPTR)res[OPT_PATTERN],&gb->Must[0],4);
  1004.  
  1005.   gb->Oval = res[OPT_OVAL];
  1006.  
  1007.   gb->Shadow = res[OPT_SHADOW];
  1008.  
  1009.   def = 1;
  1010.   if (res[OPT_SHOWFACE])
  1011.   {
  1012.     tmp = *(LONG *)res[OPT_SHOWFACE]; if ((ULONG)tmp < 5) def = tmp;
  1013.   }
  1014.   gb->Show = def;
  1015.  
  1016.   def = 2;
  1017.   if (res[OPT_HANDTYPE])
  1018.   {
  1019.     tmp = *(LONG *)res[OPT_HANDTYPE]; if ((ULONG)tmp < 4) def = tmp;
  1020.   }
  1021.   gb->HandType = def;
  1022.  
  1023.   def = 2;
  1024.   if (res[OPT_HANDWIDTH])
  1025.   {
  1026.     tmp = *(LONG *)res[OPT_HANDWIDTH]; if ((ULONG)tmp < 5) def = tmp;
  1027.   }
  1028.   gb->HandWidth = def;
  1029.  
  1030.   ReadStr(&gb->Pens[0],(STRPTR)res[OPT_DRAWPENS],(STRPTR)&Pens[0],14);
  1031.  
  1032.   def = 6;
  1033.   if (res[OPT_BORDERTYPE])
  1034.   {
  1035.     tmp = *(LONG *)res[OPT_BORDERTYPE]; if ((ULONG)tmp < 3+4+8) def = tmp;
  1036.   }
  1037.   gb->Interlace = ((tmp = def & 8) != 0); def -= tmp;
  1038.   gb->HiRes = ((tmp = def & 4) != 0); def -= tmp;
  1039.   gb->BorderCount = def;
  1040.  
  1041.  
  1042.   def = 0;
  1043.   if (res[OPT_WINDOWTYPE])
  1044.   {
  1045.     tmp = *(LONG *)res[OPT_WINDOWTYPE]; if ((ULONG)tmp < WT_LAST) def = tmp;
  1046.   }
  1047.   gb->UseImage = ((tmp = def & WT_USEIMAGE) != 0);
  1048.   gb->Fixed = ((tmp = def & WT_FIXED) != 0);
  1049.   gb->Backdrop = ((tmp = def & WT_BACKDROP) != 0);
  1050.   gb->CloseGad = ((tmp = def & WT_CLOSEGAD) != 0);
  1051.  
  1052.   def = 0;
  1053.   if (res[OPT_CHIME])
  1054.   {
  1055.     tmp = *(LONG *)res[OPT_CHIME]; if ((ULONG)tmp < 3+4) def = tmp;
  1056.   }
  1057.   gb->SmartHour = ((tmp = def & 4) != 0); def -= tmp;
  1058.   gb->Chime = def;
  1059.  
  1060.   gb->ScrNotify = res[OPT_SCRNOTIFY];
  1061.  
  1062.   def = WBP_SCREEN; if (res[OPT_WBIMAGE]) def = WBP_ROOT; gb->ImgType = def;
  1063.  
  1064.   gb->NoRemap = res[OPT_NOREMAP];
  1065.  
  1066.   if (res[OPT_IMAGE])
  1067.     if ((gb->BFInfo.PictureName=AllocVec(1+strlen((STRPTR)res[OPT_IMAGE]),MEMF_ANY)) != NULL)
  1068.       strcpy(gb->BFInfo.PictureName,(STRPTR)res[OPT_IMAGE]);
  1069.  
  1070.   if (res[OPT_PUBSCREEN])
  1071.     if ((gb->PubName=AllocVec(1+strlen((STRPTR)res[OPT_PUBSCREEN]),MEMF_ANY)) != NULL)
  1072.       strcpy(gb->PubName,(STRPTR)res[OPT_PUBSCREEN]);
  1073.  
  1074.   if (res[OPT_TASKPRI])
  1075.   {
  1076.     tmp = *(LONG *)res[OPT_TASKPRI]; if (tmp > 5) tmp = 5;
  1077.     gb->OldPri = SetTaskPri(gb->WindowPort->mp_SigTask,tmp);
  1078.     gb->ChangedPri = -1;
  1079.   }
  1080.  
  1081.   FreeArgs(args);
  1082.  
  1083.   if (rda != NULL)
  1084.     FreeDosObject(DOS_RDARGS,rda);
  1085. }
  1086.  
  1087. /*
  1088. ** init pen-buffer with `def' and replace with src (if non zero)
  1089. */
  1090.  
  1091. VOID ReadStr(UBYTE *dst,UBYTE *src,UBYTE *def,LONG cnt)
  1092. {
  1093.   CopyMem(def,dst,cnt);
  1094.  
  1095.   if (src != NULL)
  1096.     if (*src=='x' || *src=='X') /* hex */
  1097.       do
  1098.       { if (!*src++ || !*src++)
  1099.           return;
  1100.         *dst++ = (XtoD(src[-1])<<4) + XtoD(*src);
  1101.       } while (--cnt);
  1102.     else
  1103.       do /* decimal */
  1104.       { if (!*src)
  1105.           return;
  1106.         *dst++ = XtoD(*src++);
  1107.       } while (--cnt);
  1108. }
  1109.  
  1110. LONG XtoD(LONG a)
  1111. {
  1112.   if (a>='0' && a<='9')
  1113.     return (a-'0');
  1114.   if (a>='a' && a<='f')
  1115.     return (a-'a'+10);
  1116.   if (a>='A' && a<='F')
  1117.     return (a-'A'+10);
  1118.   return 0;
  1119. }
  1120.  
  1121. /***************************************************************************/
  1122. /*                                                                         */
  1123. /* open all devices                                                        */
  1124. /*                                                                         */
  1125. /***************************************************************************/
  1126.  
  1127. LONG OpenDevs()
  1128. { LONG ret = 0;
  1129.  
  1130.   if ((gb->WindowPort=CreateMsgPort()) != NULL)
  1131.     if ((gb->TimerPort=CreateMsgPort()) != NULL)
  1132.       if ((gb->TimerIO=CreateIORequest(gb->TimerPort,sizeof(struct timerequest))) != NULL)
  1133.         if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)gb->TimerIO,0))
  1134.         {
  1135.           gb->TimerOpen = -1;
  1136.           if ((gb->AudioPort=CreateMsgPort()) != NULL)
  1137.             if ((gb->AudioIO[0]=CreateIORequest(gb->AudioPort,sizeof(struct IOAudio))) != NULL)
  1138.               if ((gb->AudioIO[1]=CreateIORequest(gb->AudioPort,sizeof(struct IOAudio))) != NULL)
  1139.                 if (!OpenDevice(AUDIONAME,0,(struct IORequest *)gb->AudioIO[0],0))
  1140.                 {
  1141.                   gb->AudioOpen = -1;
  1142.                   if ((gb->WaveForm=AllocMem(8,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
  1143.                   {
  1144.                     ((ULONG *)gb->WaveForm)[0]=0x7f807f80; /* rectangle */
  1145.                     ret = 1;
  1146.                   }
  1147.                 }
  1148.         }
  1149.   return ret;
  1150. }
  1151.  
  1152. /***************************************************************************/
  1153. /*                                                                         */
  1154. /* open all libraries                                                      */
  1155. /*                                                                         */
  1156. /***************************************************************************/
  1157.  
  1158. LONG OpenLibs()
  1159. { LONG ret = 0;
  1160.  
  1161.   if ((gb->DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) != NULL)
  1162.     if ((gb->IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L)) != NULL)
  1163.       if ((gb->GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L)) != NULL)
  1164.         if ((gb->GadtoolsBase=OpenLibrary("gadtools.library",37L)) != NULL)
  1165.           if ((gb->IconBase=OpenLibrary("icon.library",37L)) != NULL)
  1166.           {
  1167.             gb->DataTypesBase = OpenLibrary("datatypes.library",39L);
  1168.             if ((gb->LocaleBase=(struct LocaleBase *)OpenLibrary("locale.library",38L)) != NULL)
  1169.             {
  1170.               gb->Catalog = OpenCatalogA(NULL,"tolleuhr.catalog",NULL);
  1171.             }
  1172.             ret = 1;
  1173.           }
  1174.   return ret;
  1175. }
  1176.  
  1177. /***************************************************************************/
  1178. /*                                                                         */
  1179. /* main function                                                           */
  1180. /*                                                                         */
  1181. /***************************************************************************/
  1182.  
  1183. VOID Main()
  1184. { struct WBStartup *wbmsg;
  1185.   struct Process *proc;
  1186.   STRPTR buf;
  1187.   ULONG mask;
  1188.  
  1189.   proc = (struct Process *)FindTask(NULL); wbmsg = NULL;
  1190.  
  1191.   if (!proc->pr_CLI)
  1192.   {
  1193.     wbmsg = (struct WBStartup *)(WaitPort(&proc->pr_MsgPort),GetMsg(&proc->pr_MsgPort));
  1194.   }
  1195.  
  1196.   if (gb->SysBase->LibNode.lib_Version >= 37)
  1197.   {
  1198.     if (OpenLibs())
  1199.     {
  1200.       if (OpenDevs())
  1201.       {
  1202.         if (GetArguments(wbmsg))
  1203.         {
  1204.           if (InitClock())
  1205.           {
  1206.             if (gb->ScrNotify)
  1207.               AddScreenNotify();
  1208.             for(;;)
  1209.             {
  1210.               mask = 1L<<SIGBREAKB_CTRL_C | 1L<<gb->WindowPort->mp_SigBit |
  1211.                      1L<<gb->TimerPort->mp_SigBit | 1L<<gb->AudioPort->mp_SigBit;
  1212.  
  1213.               if (gb->NotifyPort)
  1214.                 mask |= 1L<<gb->NotifyPort->mp_SigBit;
  1215.  
  1216.               if (gb->AboutReq)
  1217.                 mask |= 1L<<gb->AboutReq->UserPort->mp_SigBit;
  1218.  
  1219.               if (Wait(mask) & SIGBREAKF_CTRL_C) /* User-Break */
  1220.                 break;
  1221.  
  1222.               if (GetMsg(gb->TimerPort))
  1223.               {
  1224.                 if (NextTick())
  1225.                 {
  1226.                   NewTitle(); ZifferBlatt(); TestIfAlarm();
  1227.                 }
  1228.                 Zeichnen();
  1229.               }
  1230.  
  1231.               if (GetMsg(gb->AudioPort))
  1232.                 PlayNote();
  1233.  
  1234.               if (gb->NotifyHandle && !CheckNotify())
  1235.                 break;
  1236.  
  1237.               CheckAboutReq();
  1238.  
  1239.               CheckWindows();
  1240.  
  1241.               if (gb->EndAll)
  1242.                 break;
  1243.             }
  1244.             RemScreenNotify();
  1245.           }
  1246.           CloseGfx();
  1247.  
  1248.           if ((buf=gb->PubName) != NULL)
  1249.             FreeVec(buf);
  1250.  
  1251.           if ((buf=gb->BFInfo.PictureName) != NULL)
  1252.             FreeVec(buf);
  1253.  
  1254.           if (gb->ChangedPri)
  1255.             (VOID)SetTaskPri(gb->WindowPort->mp_SigTask,gb->OldPri);
  1256.  
  1257.           if ((buf=gb->NameBuf) != NULL)
  1258.             FreeVec(buf);
  1259.  
  1260.           if (gb->ChangedDir)
  1261.             (VOID)CurrentDir(gb->OldLock);
  1262.         }
  1263.       }
  1264.       CloseDevs();
  1265.     }
  1266.     CloseLibs();
  1267.   }
  1268.  
  1269.   if (wbmsg)
  1270.   {
  1271.     Forbid();
  1272.     ReplyMsg((struct Message *)wbmsg);
  1273.   }
  1274. }
  1275.  
  1276. /***************************************************************************/
  1277. /*                                                                         */
  1278. /* close all libraries                                                     */
  1279. /*                                                                         */
  1280. /***************************************************************************/
  1281.  
  1282. VOID CloseLibs()
  1283. { struct Catalog *cat;
  1284.  
  1285.   if ((cat=gb->Catalog) != NULL)
  1286.     CloseCatalog(cat);
  1287.   CloseLibrary((struct Library *)gb->LocaleBase);
  1288.   CloseLibrary(gb->DataTypesBase);
  1289.   CloseLibrary(gb->IconBase);
  1290.   CloseLibrary(gb->GadtoolsBase);
  1291.   CloseLibrary((struct Library *)gb->GfxBase);
  1292.   CloseLibrary((struct Library *)gb->IntuitionBase);
  1293.   CloseLibrary((struct Library *)gb->DOSBase);
  1294. }
  1295.  
  1296. /***************************************************************************/
  1297. /*                                                                         */
  1298. /* close all devices                                                       */
  1299. /*                                                                         */
  1300. /***************************************************************************/
  1301.  
  1302. VOID StopIO(struct IORequest *ioReq)
  1303. {
  1304.   AbortIO(ioReq); WaitIO(ioReq);
  1305. }
  1306.  
  1307. VOID CloseDevs()
  1308. { struct IORequest *io;
  1309.   APTR buf;
  1310.  
  1311.   if (gb->AudioOpen)
  1312.   {
  1313.     if (gb->AudioSent[1])
  1314.       StopIO((struct IORequest *)gb->AudioIO[1]);
  1315.     io = (struct IORequest *)gb->AudioIO[0];
  1316.     if (gb->AudioSent[0])
  1317.       StopIO(io);
  1318.     if (gb->SoundOn)
  1319.       EndTune();
  1320.     CloseDevice(io);
  1321.   }
  1322.   DeleteIORequest((struct IORequest *)gb->AudioIO[1]);
  1323.   DeleteIORequest((struct IORequest *)gb->AudioIO[0]);
  1324.   DeleteMsgPort(gb->AudioPort);
  1325.   if ((buf=gb->WaveForm) != NULL) FreeMem(buf,8);
  1326.  
  1327.   if (gb->TimerOpen)
  1328.     CloseDevice((struct IORequest *)gb->TimerIO);
  1329.   DeleteIORequest((struct IORequest *)gb->TimerIO);
  1330.   DeleteMsgPort(gb->TimerPort);
  1331.  
  1332.   DeleteMsgPort(gb->WindowPort);
  1333. }
  1334.  
  1335. /***************************************************************************/
  1336. /*                                                                         */
  1337. /* close graphic stuff                                                     */
  1338. /*                                                                         */
  1339. /***************************************************************************/
  1340.  
  1341. VOID NewSize1()
  1342. { PLANEPTR buf,*p;
  1343.   LONG i;
  1344.  
  1345.   if ((buf=gb->Buf) != NULL)
  1346.     FreeRaster(buf,gb->Width2,gb->Height2);
  1347.  
  1348.   p=&gb->BitMap1.Planes[0];
  1349.   if ((i=gb->BitMap1.Depth) > 0)
  1350.     do
  1351.     { if ((buf=*p) != NULL)
  1352.         FreeRaster(buf,gb->Width2,gb->Height2);
  1353.       *p++=NULL;
  1354.     } while(--i);
  1355. }
  1356.  
  1357. /*
  1358. ** discard `About'
  1359. */
  1360.  
  1361. VOID CloseAboutReq()
  1362. {
  1363.   FreeSysRequest(gb->AboutReq); gb->AboutReq = NULL;
  1364. }
  1365.  
  1366. /*
  1367. ** discard all windows and other gfx stuff
  1368. */
  1369.  
  1370. VOID CloseGfx()
  1371. { struct Window *win;
  1372.  
  1373.   if (gb->TimerSent)
  1374.   {
  1375.     StopIO(&gb->TimerIO->tr_node); gb->TimerSent = 0;
  1376.   }
  1377.   NewSize1();
  1378.   CloseAboutReq();
  1379.   FreeWindow(&gb->AlarmWin);
  1380.   FreeWindow(&gb->ColorWin);
  1381.   win = gb->MainWin; gb->Top = win->TopEdge; gb->Left = win->LeftEdge;
  1382.   CloseWindowSafely(win);
  1383.   gb->MainWin = NULL;
  1384.   FreeMenus(gb->Menus);
  1385.   gb->Menus = NULL;
  1386.   FreeVisualInfo(gb->VisualInfo);
  1387.   gb->VisualInfo = NULL;
  1388.   DisposeDTObject(gb->BFInfo.PictureObject);
  1389.   gb->BFInfo.PictureObject = NULL;
  1390.   gb->BFInfo.BitMapHeader = NULL;
  1391.   gb->BFInfo.BitMap = NULL;
  1392. }
  1393.  
  1394. /*
  1395. ** close a tool window
  1396. */
  1397.  
  1398. VOID FreeWindow(struct WinGad *wg)
  1399. {
  1400.   CloseWindowSafely(wg->Win); wg->Win = NULL;
  1401.   FreeGadgets(wg->Gad); wg->Gad = NULL;
  1402. }
  1403.  
  1404. /*
  1405. ** close a window with shared IDCMP
  1406. */
  1407.  
  1408. VOID CloseWindowSafely(struct Window *win)
  1409. { struct Node *msg,*succ;
  1410.  
  1411.   if (win != NULL)
  1412.   {
  1413.     Forbid();
  1414.     msg=win->UserPort->mp_MsgList.lh_Head; /* assumes valid port */
  1415.     while ((succ=msg->ln_Succ)!=NULL)
  1416.     { if (((struct IntuiMessage *)msg)->IDCMPWindow==win)
  1417.       {
  1418.         Remove(msg); ReplyMsg((struct Message *)msg);
  1419.       }
  1420.       msg=succ;
  1421.     }
  1422.     win->UserPort=NULL;
  1423.     ModifyIDCMP(win,0L);
  1424.     Permit();
  1425.     ClearMenuStrip(win);
  1426.     CloseWindow(win);
  1427.   }
  1428. }
  1429.  
  1430. /***************************************************************************/
  1431. /*                                                                         */
  1432. /* remove screen notification                                              */
  1433. /*                                                                         */
  1434. /***************************************************************************/
  1435.  
  1436. VOID RemScreenNotify()
  1437. { APTR handle;
  1438.  
  1439.   if ((handle=gb->NotifyHandle) != NULL)
  1440.     while (!RemWorkbenchClient(handle)) Delay(10);
  1441.   gb->NotifyHandle = NULL;
  1442.   DeleteMsgPort(gb->NotifyPort);
  1443.   gb->NotifyPort = NULL;
  1444.   CloseLibrary(gb->ScreenNotifyBase);
  1445.   gb->ScreenNotifyBase = NULL;
  1446. }
  1447.  
  1448. /***************************************************************************/
  1449. /*                                                                         */
  1450. /* check screen notification                                               */
  1451. /*                                                                         */
  1452. /***************************************************************************/
  1453.  
  1454. LONG CheckNotify()
  1455. { struct ScreenNotifyMessage *snm;
  1456.   LONG ret=1;
  1457.  
  1458.   while ((snm=(struct ScreenNotifyMessage *)GetMsg(gb->NotifyPort)) != NULL)
  1459.   {
  1460.     if (snm->snm_Type == SCREENNOTIFY_TYPE_WORKBENCH)
  1461.       switch((LONG)snm->snm_Value)
  1462.       {
  1463.         case TRUE:
  1464.           if (!ret || (ret=InitClock()))
  1465.             break;
  1466.         case FALSE:
  1467.           CloseGfx();
  1468.         default:
  1469.           break;
  1470.       }
  1471.     ReplyMsg(&snm->snm_Message);
  1472.   }
  1473.   return ret;
  1474. }
  1475.  
  1476. /***************************************************************************/
  1477. /*                                                                         */
  1478. /* process all input events                                                */
  1479. /*                                                                         */
  1480. /***************************************************************************/
  1481.  
  1482. VOID CheckAboutReq()
  1483. { struct Window *req;
  1484.  
  1485.   if ((req=gb->AboutReq) != NULL)
  1486.     if (SysReqHandler(req,NULL,FALSE) != -2)
  1487.       CloseAboutReq();
  1488. }
  1489.  
  1490. /*
  1491. ** process all windows with shared IDCMP
  1492. */
  1493.  
  1494. VOID CheckWindows()
  1495. { struct IntuiMessage *imsg;
  1496.   struct Window *iwin;
  1497.   ULONG class,code;
  1498.   APTR iadr;
  1499.   LONG tmp;
  1500.  
  1501.   while ((imsg=GT_GetIMsg(gb->WindowPort)) != NULL)
  1502.   { class = imsg->Class;
  1503.     code  = imsg->Code;
  1504.     iadr  = imsg->IAddress;
  1505.     iwin  = imsg->IDCMPWindow;
  1506.     GT_ReplyIMsg(imsg);
  1507.     if (gb->MainWin == iwin)
  1508.     { switch (class)
  1509.       { case NEWSIZE:
  1510.           NewSize1();
  1511.           if ((gb->EndAll=NewSize2()))
  1512.             return;
  1513.           Rahmen();
  1514.           ZifferBlatt();
  1515.           Zeichnen();
  1516.           break;
  1517.         case REFRESHWINDOW:
  1518.           gb->ReDrawx1=(tmp=gb->BoLeft);
  1519.           gb->ReDrawx2=tmp+gb->Width2-1;
  1520.           gb->ReDrawy1=(tmp=gb->BoTop);
  1521.           gb->ReDrawy2=tmp+gb->Height2-1;
  1522.           BeginRefresh(gb->MainWin);
  1523.           Rahmen();
  1524.           Zeichnen();
  1525.           EndRefresh(gb->MainWin,TRUE);
  1526.           break;
  1527.         case MENUPICK:
  1528.           HandleMenus(code);
  1529.           if (gb->EndAll)
  1530.             return;
  1531.           break;
  1532.         case CLOSEWINDOW:
  1533.           if ((gb->EndAll=gb->CloseGad))
  1534.             return;
  1535.           break;
  1536.         case ACTIVEWINDOW:
  1537.           gb->Active = -1;
  1538.           Rahmen();
  1539.           break;
  1540.         case INACTIVEWINDOW:
  1541.           gb->Active = 0;
  1542.           Rahmen();
  1543.           break;
  1544.       }
  1545.     }
  1546.     else
  1547.       if (gb->ColorWin.Win == iwin)
  1548.       { if (class == CLOSEWINDOW || class == GADGETUP)
  1549.         { FreeWindow(&gb->ColorWin);
  1550.           if (class!=CLOSEWINDOW) /* kann nur das Palette-Gadget sein */
  1551.           { *gb->Color = code;
  1552.             SetPattern();
  1553.             NewSize1();
  1554.             if ((gb->EndAll=NewSize2()))
  1555.               return;
  1556.             Rahmen();
  1557.             ZifferBlatt();
  1558.             Zeichnen();
  1559.           }
  1560.         }
  1561.       }
  1562.       else
  1563.         if (gb->AlarmWin.Win == iwin)
  1564.         { if (class==CLOSEWINDOW || class==MOUSEMOVE || class==GADGETUP)
  1565.           { if (class!=CLOSEWINDOW)
  1566.             { switch(((struct Gadget *)iadr)->GadgetID)
  1567.               { case 1:
  1568.                   gb->St = code;
  1569.                   goto endit;
  1570.                 case 2:
  1571.                   gb->Mi = code;
  1572.                   goto endit;
  1573.                 case 3:
  1574.                   gb->AlStd = gb->St; gb->AlMin = gb->Mi; gb->Alarm = -1;
  1575.                 case 4:
  1576.                   break;
  1577.               }
  1578.             }
  1579.             FreeWindow(&gb->AlarmWin);
  1580.             if (gb->Alarm)
  1581.             { struct MenuItem *item=ItemAddress(gb->Menus,FULLMENUNUM(1,7,1));
  1582.               if (!(item->Flags&CHECKED))
  1583.               { ClearMenuStrip(gb->MainWin);
  1584.                 item->Flags |= CHECKED;
  1585.                 ResetMenuStrip(gb->MainWin,gb->Menus);
  1586.               }
  1587.             }
  1588. endit:      ;
  1589.           }
  1590.         }
  1591.   }
  1592. }
  1593.  
  1594. /*
  1595. ** function for Menu-Handling
  1596. */
  1597.  
  1598. CONST UWORD ColorWinInfo[] = {
  1599.   CLOSEWINDOW | PALETTEIDCMP, MSG_CHOOSE,
  1600.   1,
  1601.   4,2,144,68,0,PALETTE_KIND,
  1602. };
  1603.  
  1604. CONST UWORD AlarmWinInfo[] = {
  1605.   CLOSEWINDOW | BUTTONIDCMP | SLIDERIDCMP, MSG_ALARM,
  1606.   4,
  1607.   42,15,20,39,0         ,SLIDER_KIND,
  1608.   82,15,20,39,0         ,SLIDER_KIND,
  1609.    2,58,70,12,MSG_USE   ,BUTTON_KIND,
  1610.   76,58,70,12,MSG_CANCEL,BUTTON_KIND,
  1611. };
  1612.  
  1613. CONST struct TagItem AlarmGadTags1[] = {
  1614.   { GTSL_Min        ,1               },
  1615.   { GTSL_Max        ,12              },
  1616.   { GTSL_MaxLevelLen,10              },
  1617.   { GTSL_LevelPlace ,PLACETEXT_ABOVE },
  1618.   { PGA_FREEDOM     ,LORIENT_VERT    },
  1619.   { GA_RelVerify    ,TRUE            },
  1620.   { TAG_DONE        ,NULL            }
  1621. };
  1622.  
  1623. CONST struct TagItem AlarmGadTags2[] = {
  1624.   { GTSL_Min        ,0               },
  1625.   { GTSL_Max        ,59              },
  1626.   { GTSL_MaxLevelLen,5               },
  1627.   { GTSL_LevelPlace ,PLACETEXT_ABOVE },
  1628.   { PGA_FREEDOM     ,LORIENT_VERT    },
  1629.   { GA_RelVerify    ,TRUE            },
  1630.   { TAG_DONE        ,NULL            }
  1631. };
  1632.  
  1633. VOID HandleMenus(ULONG code)
  1634. { struct TagItem tags[6],*tt[4];
  1635.   struct MenuItem *item;
  1636.   struct Window *req;
  1637.   ULONG mnum,inum,snum,*p,ok=1;
  1638.   BYTE check;
  1639.  
  1640.   while ((UWORD)code != MENUNULL)
  1641.   {
  1642.     item = ItemAddress(gb->Menus,code);
  1643.     mnum = MENUNUM(code); inum = ITEMNUM(code); snum = SUBNUM(code);
  1644.     (UWORD)code = item->NextSelect;
  1645.  
  1646.     switch (mnum)
  1647.     {
  1648.        case 0: /* Project */
  1649.          switch (inum)
  1650.          {
  1651.            case 0: /* About */
  1652.              if (gb->AboutReq == NULL)
  1653.              {
  1654.                gb->EasyBuf.es_StructSize   = 5*sizeof(ULONG);
  1655.                gb->EasyBuf.es_Flags        = 0;
  1656.                gb->EasyBuf.es_Title        = GetCatalogString(MSG_ABOUT);
  1657.                gb->EasyBuf.es_TextFormat   = PROGNAME;
  1658.                gb->EasyBuf.es_GadgetFormat = GetCatalogString(MSG_DESCRIPTION);
  1659.                req = BuildEasyRequestArgs(gb->MainWin,&gb->EasyBuf,NULL,NULL);
  1660.                if ((ULONG)req>1)
  1661.                  gb->AboutReq = req;
  1662.              }
  1663.              break;
  1664.            case 1: /* Quit */
  1665.              gb->EndAll = -1; return;
  1666.              break;
  1667.          }
  1668.          break;
  1669.        case 1: /* Settings */
  1670.          check = (item->Flags&CHECKED ? 1 : 0);
  1671.          switch (inum)
  1672.          {
  1673.            case  0: /* Seconds */
  1674.              gb->Seconds = check;
  1675.              StopIO(&gb->TimerIO->tr_node);
  1676.              NextTick();
  1677.              break;
  1678.            case  1: /* Oval */
  1679.              gb->Oval = check;
  1680.              break;
  1681.            case  2: /* Show */
  1682.              if (check)
  1683.                gb->Show = snum;
  1684.              break;
  1685.            case  3: /* Hands */
  1686.              if (check)
  1687.                switch (snum)
  1688.                { case 0: case 1: case 2: case 3:
  1689.                    gb->HandType  = snum;
  1690.                    break;
  1691.                  case 5: case 6: case 7: case 8: case 9:
  1692.                    gb->HandWidth = snum-5;
  1693.                    break;
  1694.                }
  1695.              break;
  1696.            case  4: /* Shadow */
  1697.              gb->Shadow = check;
  1698.              break;
  1699.            case  5: /* Border */
  1700.              switch (snum)
  1701.              { case 0: case 1: case 2:
  1702.                  if (check)
  1703.                    gb->BorderCount = snum;
  1704.                  break;
  1705.                case 4:
  1706.                  gb->HiRes = check;
  1707.                  break;
  1708.                case 5:
  1709.                  gb->Interlace = check;
  1710.                  break;
  1711.              }
  1712.              break;
  1713.            case  6: /* Chime */
  1714.              switch (snum)
  1715.              { case 0: case 1: case 2:
  1716.                  if (check)
  1717.                    gb->Chime = snum;
  1718.                  break;
  1719.                case 4:
  1720.                  gb->SmartHour = check;
  1721.                  break;
  1722.              }
  1723.            case  7: /* Alarm */
  1724.              switch (snum)
  1725.              {
  1726.                case 0:
  1727.                  if (gb->AlarmWin.Win == NULL)
  1728.                  {
  1729.                    gb->St = gb->AlStd; tt[0] = &tags[0];
  1730.                    p = (ULONG *)tt[0];
  1731.                    *p++ = GTSL_Level; *p++ = gb->AlStd;
  1732.                    *p++ = GTSL_LevelFormat; *p++ = (ULONG)"%2ld";
  1733.                    *p++ = TAG_MORE; *p = (ULONG)&AlarmGadTags1[0];
  1734.                    gb->Mi = gb->AlMin; tt[1] = &tags[3];
  1735.                    p = (ULONG *)tt[1];
  1736.                    *p++ = GTSL_Level; *p++ = gb->AlMin;
  1737.                    *p++ = GTSL_LevelFormat; *p++ = (ULONG)"%02ld";
  1738.                    *p++ = TAG_MORE; *p = (ULONG)&AlarmGadTags2[0];
  1739.                    tt[2] = NULL; tt[3] = NULL;
  1740.                    CreateRequest(&gb->AlarmWin,(struct wInfo *)&AlarmWinInfo[0],&tt[0]);
  1741.                  }
  1742.                  break;
  1743.                case 1:
  1744.                  gb->Alarm = check;
  1745.                  break;
  1746.              }
  1747.              break;
  1748.            case  8: /* Window Properties */
  1749.              switch (snum)
  1750.              {
  1751.                case 0:
  1752.                  gb->CloseGad = check;
  1753.                  break;
  1754.                case 1:
  1755.                  if (gb->Backdrop != check)
  1756.                    { gb->Backdrop = check; ok=0; }
  1757.                  break;
  1758.                case 2:
  1759.                  gb->Fixed = check;
  1760.                  break;
  1761.                case 3:
  1762.                  gb->UseImage = check;
  1763.                  break;
  1764.              }
  1765.              break;
  1766.            case 10: /* Save Settings */
  1767.              SaveSettings();
  1768.              break;
  1769.          }
  1770.          break;
  1771.        case 2: /* Colours */
  1772.        case 3: /* Pattern */
  1773.          if (gb->ColorWin.Win == NULL)
  1774.          {
  1775.            gb->Color = (mnum == 2 ? &gb->Pens[inum] : &gb->Must[inum]);
  1776.            tt[0] = &tags[0];
  1777.            p = (ULONG *)tt[0];
  1778.            *p++ = GTPA_Depth; *p++ = gb->BitMap1.Depth; *p = TAG_DONE;
  1779.            CreateRequest(&gb->ColorWin,(struct wInfo *)&ColorWinInfo[0],&tt[0]);
  1780.          }
  1781.          break;
  1782.     }
  1783.   }
  1784.   if (!ok)
  1785.   {
  1786.     CloseGfx(); gb->EndAll=(InitClock() == 0);
  1787.   }
  1788.   else
  1789.   {
  1790.     NewSize1();
  1791.     if ((gb->EndAll=NewSize2()))
  1792.       return;
  1793.     Rahmen();
  1794.     ZifferBlatt();
  1795.     Zeichnen();
  1796.   }
  1797. }
  1798.  
  1799. /***************************************************************************/
  1800. /*                                                                         */
  1801. /* resize invisible gadgets, init hidden drawing area                      */
  1802. /*                                                                         */
  1803. /***************************************************************************/
  1804.  
  1805. CONST WORD Sizes[][4] = { /* Für Gadgets */
  1806.   /* depth */ { -3, 0, 3, 2 },
  1807.   /* size  */ { -3,-2, 3, 2 },
  1808.   /* drag  */ {  0, 2, 0,-4 },
  1809.   /* close */ {  0, 0, 3, 2 }
  1810. };
  1811.  
  1812. LONG NewSize2()
  1813. { struct Window *win;
  1814.   struct Gadget *gad;
  1815.   PLANEPTR *p;
  1816.   LONG tmp,w,w2,h,h2,bc,ret;
  1817.   WORD i,j,k,newsize,*s;
  1818.  
  1819.   bc = gb->BorderCount;
  1820.   tmp = bc; if (gb->HiRes) tmp += (bc==2)<<1;
  1821.   gb->BoLeft = tmp;
  1822.   tmp = bc; if (gb->Interlace) tmp += (bc==2)<<1;
  1823.   gb->BoTop  = tmp;
  1824.  
  1825.   win = gb->MainWin;
  1826.  
  1827.   w = win->Width;  gb->Width  = w;
  1828.   h = win->Height; gb->Height = h;
  1829.  
  1830.   w2 = w-(gb->BoLeft<<1); gb->Width2  = w2;
  1831.   h2 = h-(gb->BoTop<<1);  gb->Height2 = h2;
  1832.  
  1833.   gb->xDouble = (gb->xMask == -2 && w2 > 12);
  1834.   gb->yDouble = (gb->yMask == -2 && h2 > 12);
  1835.  
  1836.   tmp = 0; if (w2 > 25) tmp = (w2 > 50 ? 2 : 1);
  1837.   gb->xOffset = tmp;
  1838.   tmp = 0; if (h2 > 25) tmp = (h2 > 50 ? 2 : 1);
  1839.   gb->yOffset = tmp;
  1840.  
  1841.   tmp = w; if (w > h) tmp = h; newsize = tmp/8;
  1842.  
  1843.   RemoveGList(gb->MainWin,gb->MainWin->FirstGadget,-1);
  1844.   if (gb->GadSize != newsize)
  1845.   { gb->GadSize = newsize;
  1846.     for (gad=&gb->GadgetBuf[0],s=(WORD *)&Sizes[0],i=GB_GADCOUNT-1; i>=0; gad++,i--)
  1847.       for (j=4-1,k=2; j>=0; k++,j--)
  1848.         ((UWORD *)gad)[k] = *s++*gb->GadSize;
  1849.   }
  1850.   tmp=4; gad=&gb->GadgetBuf[0]; if (gb->Fixed) {gad+=3; tmp-=3;}
  1851.   AddGList(gb->MainWin,gad,0,tmp,NULL);
  1852.  
  1853.   InitBitMap(&gb->BitMap1,PUB_SCREEN->BitMap.Depth,gb->Width2,gb->Height2);
  1854.  
  1855.   ret = 1;
  1856.  
  1857.   for(p=&gb->BitMap1.Planes[0],i=gb->BitMap1.Depth; i!=0; i--)
  1858.     if ((*p++=AllocRaster(gb->Width2,gb->Height2)) == NULL)
  1859.       return ret;
  1860.  
  1861.   InitRastPort(&gb->RPort2); gb->RPort2.BitMap = &gb->BitMap1;
  1862.  
  1863.   if ((gb->Buf=AllocRaster(gb->Width2,gb->Height2)) != NULL)
  1864.   {
  1865.     gb->RPort2.TmpRas  = InitTmpRas(&gb->TempRas,gb->Buf,RASSIZE(gb->Width2,gb->Height2));
  1866.     InitArea(&gb->AreaInfo,&gb->Table[0],5);
  1867.     gb->RPort2.AreaInfo= &gb->AreaInfo;
  1868.     ret = 0;
  1869.   }
  1870.  
  1871.   return ret;
  1872. }
  1873.  
  1874. /***************************************************************************/
  1875. /*                                                                         */
  1876. /* screen title will show the current date                                 */
  1877. /*                                                                         */
  1878. /***************************************************************************/
  1879.  
  1880. VOID NewTitle()
  1881. {
  1882.   struct DateTimeInfo *dti = &gb->DateTime;
  1883.   STRPTR p;
  1884.  
  1885.   DateStamp(&dti->dat.dat_Stamp);
  1886.   dti->dat.dat_StrDay  = &dti->buf[ 0];
  1887.   dti->dat.dat_StrDate = &dti->buf[18];
  1888.   DateToStr(&dti->dat);
  1889.   p=dti->dat.dat_StrDay;
  1890.   do {} while (*p++);
  1891.   p[-1] = ','; *p++ = ' ';
  1892.   strcpy(p,dti->dat.dat_StrDate);
  1893.   SetWindowTitles(gb->MainWin,(UBYTE *)-1L,dti->dat.dat_StrDay);
  1894. }
  1895.  
  1896. /***************************************************************************/
  1897. /*                                                                         */
  1898. /* issue a timer request                                                   */
  1899. /*                                                                         */
  1900. /***************************************************************************/
  1901.  
  1902. ULONG NextTick()
  1903. { struct timerequest *treq = gb->TimerIO;
  1904.   ULONG tmp,old,std,min,sec;
  1905.  
  1906.   treq->tr_node.io_Command = TR_GETSYSTIME;
  1907.   DoIO(&treq->tr_node);
  1908.   treq->tr_time.tv_micro = 1100000-treq->tr_time.tv_micro;
  1909.                                /* ^ Ein ganz besonders netter Effekt: Das Timer */
  1910.                                /* Device rundet aktuelle Zeit und Wartezeit ab  */
  1911.   sec = treq->tr_time.tv_secs;
  1912.   tmp = 0; if (!gb->Seconds) tmp = 59-sec%60;
  1913.   treq->tr_time.tv_secs = tmp;
  1914.   treq->tr_node.io_Command = TR_ADDREQUEST;
  1915.   SendIO(&treq->tr_node);
  1916.   gb->TimerSent = -1;
  1917.  
  1918.   old=gb->Min;
  1919.   min=sec/60;
  1920.   gb->Sec=sec%60;
  1921.   std=min/12;
  1922.   gb->Min=(min%=60);
  1923.   gb->Std=std%60;
  1924.  
  1925.   return (min-old); /* sec==0 ist unzuverlässig bei hoher CPU-Auslastung */
  1926. }
  1927.  
  1928. /***************************************************************************/
  1929. /*                                                                         */
  1930. /* draw border                                                             */
  1931. /*                                                                         */
  1932. /***************************************************************************/
  1933.  
  1934. VOID Rahmen()
  1935. { struct RastPort *rp = gb->RPort1;
  1936.   ULONG pen,pen11,pen12;
  1937.   LONG w,h,bl,bt;
  1938.  
  1939.   if (gb->BorderCount)
  1940.   {
  1941.     w = gb->Width; h = gb->Height;
  1942.  
  1943.     pen11 = gb->Pens[11]; pen12 = gb->Pens[12];
  1944.     if (gb->Active && gb->BorderCount == 1)
  1945.     {
  1946.       pen=pen11; pen11=pen12; pen12=pen;
  1947.     }
  1948.  
  1949.     SetAPen(rp,pen11);
  1950.     Move(rp,1  ,h-1);
  1951.     Draw(rp,w-1,h-1);
  1952.     Draw(rp,w-1,1  );
  1953.     SetAPen(rp,pen12);
  1954.     Move(rp,0  ,h-1);
  1955.     Draw(rp,0  ,0  );
  1956.     Draw(rp,w-1,0  );
  1957.  
  1958.     if (gb->BorderCount == 2)
  1959.     {
  1960.       bl = gb->BoLeft; bt = gb->BoTop;
  1961.       SetAPen(rp,gb->Pens[12]);
  1962.       Move(rp,bl  ,h-bt);
  1963.       Draw(rp,w-bl,h-bt);
  1964.       Draw(rp,w-bl,bt  );
  1965.       SetAPen(rp,gb->Pens[11]);
  1966.       Move(rp,bl-1,h-bt);
  1967.       Draw(rp,bl-1,bt-1);
  1968.       Draw(rp,w-bl,bt-1);
  1969.       pen = gb->Pens[10]; if (gb->Active) pen = gb->Pens[13];
  1970.       SetAPen(rp,pen);
  1971.  
  1972.       if (gb->HiRes)
  1973.       {
  1974.         RectFill(rp,1,1,2,h-2);
  1975.         RectFill(rp,w-3,1,w-2,h-2);
  1976.       }
  1977.  
  1978.       if (gb->Interlace)
  1979.       {
  1980.         RectFill(rp,1,1,w-2,2);
  1981.         RectFill(rp,1,h-3,w-2,h-2);
  1982.       }
  1983.     }
  1984.   }
  1985.   SetAPen(rp,gb->Pens[0]);
  1986. }
  1987.  
  1988. /***************************************************************************/
  1989. /*                                                                         */
  1990. /* create the clock                                                        */
  1991. /*                                                                         */
  1992. /***************************************************************************/
  1993.  
  1994. CONST BYTE sinus[] = { /* sinus-Tabelle */
  1995.   0,13,26,39,52,64,75,85,94,103,110,116,121,124,126,
  1996.   127,126,124,121,116,110,103,94,85,75,64,52,39,26,13,
  1997.   0,-13,-26,-39,-52,-64,-75,-85,-94,-103,-110,-116,-121,-124,-126,
  1998.   -127,-126,-124,-121,-116,-110,-103,-94,-85,-75,-64,-52,-39,-26,-13
  1999. },
  2000.            cosinus[] = { /* cosinus-Tabelle */
  2001.   127,126,124,121,116,110,103,94,85,75,64,52,39,26,13,
  2002.   0,-13,-26,-39,-52,-64,-75,-85,-94,-103,-110,-116,-121,-124,-126,
  2003.   -127,-126,-124,-121,-116,-110,-103,-94,-85,-75,-64,-52,-39,-26,-13,
  2004.   0,13,26,39,52,64,75,85,94,103,110,116,121,124,126
  2005. };
  2006.  
  2007. CONST BYTE srect[] = { /* Für rechteckiges Zifferblatt */
  2008.   0,13,27,41,57,73,92,111,124,127,127,127,127,127,127,
  2009.   127,127,127,127,127,127,127,124,111,92,73,57,41,27,13,
  2010.   0,-13,-27,-41,-57,-73,-92,-111,-124,-127,-127,-127,-127,-127,-127,
  2011.   -127,-127,-127,-127,-127,-127,-127,-124,-111,-92,-73,-57,-41,-27,-13
  2012. },
  2013.            crect[] = {
  2014.   127,127,127,127,127,127,127,124,111,92,73,57,41,27,13,
  2015.   0,-13,-27,-41,-57,-73,-92,-111,-124,-127,-127,-127,-127,-127,-127,
  2016.   -127,-127,-127,-127,-127,-127,-127,-124,-111,-92,-73,-57,-41,-27,-13,
  2017.   0,13,27,41,57,73,92,111,124,127,127,127,127,127,127
  2018. };
  2019.  
  2020. CONST UBYTE pent[] = { /* Pen-Tabelle f. Zifferblatt */
  2021.   6,8,8,7,8,8,7,8,8,7,8,8
  2022. };
  2023.  
  2024. CONST BYTE dx1[] = { /* Daten für Zifferblatt */
  2025.   -2, 2, 1,-2, 1, 2,-2,-2,-1,-2,-1,-2
  2026. },
  2027.            dy1[] = {
  2028.   -4,-1,-2,-2, 2, 1,-2, 1, 2,-2,-2,-1
  2029. },
  2030.            dx2[] = {
  2031.    4,-2, 1, 4, 1,-2, 4, 2,-1, 4,-1, 2
  2032. },
  2033.            dy2[] = {
  2034.    0, 3, 2, 0,-2,-3, 0,-3,-2, 0, 2, 3
  2035. },
  2036.            dx3[] = {
  2037.    0,-2,-3, 0,-3,-2, 0, 2, 3, 0, 3, 2
  2038. },
  2039.            dy3[] = {
  2040.    8,-1, 2, 4,-2, 1, 4, 1,-2, 4, 2,-1
  2041. },
  2042.            dx4[] = {
  2043.   -4, 2,-1,-4,-1, 2,-4,-2, 1,-4, 1,-2
  2044. },
  2045.            dy4[] = {
  2046.    0,-3,-2, 0, 2, 3, 0, 3, 2, 0,-2,-3
  2047. };
  2048.  
  2049. VOID ZifferBlatt()
  2050. { struct RastPort *rp = &gb->RPort2;
  2051.   LONG i,a,b,c,x,y,bt,bl;
  2052.  
  2053.   if (gb->BFInfo.BitMap && gb->BFInfo.BitMapHeader && gb->UseImage)
  2054.   {
  2055.     CopyTiledBitMap(gb->BFInfo.BitMap,
  2056.                     gb->BFInfo.BitMapHeader->bmh_Width,
  2057.                     gb->BFInfo.BitMapHeader->bmh_Height,
  2058.                     &gb->BitMap1,gb->Width2,gb->Height2);
  2059.   }
  2060.   else
  2061.   {
  2062.     BNDRYOFF (rp);
  2063.     SetAPen  (rp,-1);
  2064.     SetAfPt  (rp,&gb->Muster[0][0],-1);
  2065.     RectFill (rp,0,0,gb->Width2-1,gb->Height2-1);
  2066.     SetAfPt  (rp,0,0);
  2067.   }
  2068.  
  2069.   i = gb->Show; a = (i > 1 ? (i == 3 ? 60 : 15) : (i ? 5 : 1));
  2070.   if (i < 4)
  2071.     for (i=0; i<60; i+=a)
  2072.     { x = gb->Width2 /2 + (((gb->Oval ?   sinus[i] : srect[i])*gb->Width2 /300) & gb->xMask);
  2073.       y = gb->Height2/2 - (((gb->Oval ? cosinus[i] : crect[i])*gb->Height2/300) & gb->yMask);
  2074.       if (i%5)
  2075.       { if (i%5==1)
  2076.         { c=gb->Pens[9];
  2077.           SetAPen(rp,c);
  2078.           SetOPen(rp,c);
  2079.         }
  2080.         AreaMove (rp,x+gb->Width2/100,y);
  2081.         AreaDraw (rp,x,y+gb->Height2/100);
  2082.         AreaDraw (rp,x-gb->Width2/100,y);
  2083.         AreaDraw (rp,x,y-gb->Height2/100);
  2084.         AreaEnd  (rp);
  2085.       }
  2086.       else
  2087.       {
  2088.         b=i/5;
  2089.         c=gb->Pens[pent[b]];
  2090.         SetAPen(rp,c);
  2091.         SetOPen(rp,c);
  2092.         AreaMove (rp,x+=gb->Width2*dx1[b]/100,y+=gb->Height2*dy1[b]/100);
  2093.         AreaDraw (rp,x+=gb->Width2*dx2[b]/100,y+=gb->Height2*dy2[b]/100);
  2094.         AreaDraw (rp,x+=gb->Width2*dx3[b]/100,y+=gb->Height2*dy3[b]/100);
  2095.         AreaDraw (rp,x+=gb->Width2*dx4[b]/100,y+=gb->Height2*dy4[b]/100);
  2096.         AreaEnd  (rp);
  2097.       }
  2098.     }
  2099.   if (gb->Shadow)
  2100.   { Zeiger(gb->Std,440,1,gb->Pens[5],gb->Pens[5]);
  2101.     Zeiger(gb->Min,300,1,gb->Pens[5],gb->Pens[5]); }
  2102.   Zeiger(gb->Std,440,0,gb->Pens[3],gb->Pens[4]);
  2103.   Zeiger(gb->Min,300,0,gb->Pens[1],gb->Pens[2]);
  2104.  
  2105.   bl = gb->BoLeft;
  2106.   gb->ReDrawx1 = bl; gb->ReDrawx2 = bl + gb->Width2 -1;
  2107.   bt = gb->BoTop;
  2108.   gb->ReDrawy1 = bt; gb->ReDrawy2 = bt + gb->Height2-1;
  2109. }
  2110.  
  2111. /*
  2112. ** create hands
  2113. */
  2114.  
  2115. CONST LONG HandWidth[] = {
  2116.   4000,3250,2500,1750,1000
  2117. };
  2118.  
  2119. VOID Zeiger(ULONG winkel,LONG lfactor,LONG offset,LONG apen,LONG open)
  2120. { struct RastPort *rp;
  2121.   LONG x0,y0,x1,y1,x2,y2,tmp;
  2122.  
  2123.   tmp = gb->Width2;
  2124.   x2 = sinus  [winkel]*tmp/lfactor;
  2125.   x1 = cosinus[winkel]*tmp/HandWidth[gb->HandWidth];
  2126.   x0 = tmp/2 + (offset ? gb->xOffset : 0);
  2127.  
  2128.   tmp = gb->Height2;
  2129.   y2 = cosinus[winkel]*tmp/lfactor;
  2130.   y1 = sinus  [winkel]*tmp/HandWidth[gb->HandWidth];
  2131.   y0 = tmp/2 + (offset ? gb->yOffset : 0);
  2132.  
  2133.   rp = &gb->RPort2;
  2134.  
  2135.   SetAPen(rp,apen);
  2136.   SetOPen(rp,open);
  2137.  
  2138.   switch (gb->HandType)
  2139.   { case 0:
  2140.       SetAPen(rp,open);
  2141.       Move (rp,x0,y0);
  2142.       Draw (rp,x0+x2,y0-y2);
  2143.       if (gb->xDouble)
  2144.       { Move (rp,1+x0,y0);
  2145.         Draw (rp,1+x0+x2,y0-y2); }
  2146.       if (gb->yDouble)
  2147.       { Move (rp,x0,1+y0);
  2148.         Draw (rp,x0+x2,1+y0-y2); }
  2149.       break;
  2150.     case 1:
  2151.       AreaMove (rp,x0+x2     ,y0-y2     );
  2152.       AreaDraw (rp,x0+x1-x2/4,y0+y1+y2/4);
  2153.       AreaDraw (rp,x0-x1-x2/4,y0-y1+y2/4);
  2154.       AreaEnd  (rp);
  2155.       break;
  2156.     case 2:
  2157.       AreaMove (rp,x0+x2  ,y0-y2  );
  2158.       AreaDraw (rp,x0+x1  ,y0+y1  );
  2159.       AreaDraw (rp,x0-x2/4,y0+y2/4);
  2160.       AreaDraw (rp,x0-x1  ,y0-y1  );
  2161.       AreaEnd  (rp);
  2162.       break;
  2163.     case 3:
  2164.       AreaMove (rp,x0+=x2-x1/2,y0-=y2+y1/2);
  2165.       AreaDraw (rp,x0+=x1     ,y0+=y1     );
  2166.       AreaDraw (rp,x0-=x2*5/4 ,y0+=y2*5/4 );
  2167.       AreaDraw (rp,x0-=x1     ,y0-=y1     );
  2168.       AreaEnd  (rp);
  2169.       break;
  2170.   }
  2171. }
  2172.  
  2173. /***************************************************************************/
  2174. /*                                                                         */
  2175. /* display the clock (blit from the `hidden' window to the real one)       */
  2176. /*                                                                         */
  2177. /***************************************************************************/
  2178.  
  2179. VOID Zeichnen()
  2180. { struct RastPort *rp = gb->RPort1;
  2181.   LONG tmp,x1,y1,x2,y2;
  2182.  
  2183.   BltBitMapRastPort(&gb->BitMap1,gb->ReDrawx1-gb->BoLeft,gb->ReDrawy1-gb->BoTop,
  2184.                     rp,gb->ReDrawx1,gb->ReDrawy1,gb->ReDrawx2-gb->ReDrawx1+1,
  2185.                     gb->ReDrawy2-gb->ReDrawy1+1,0xc0);
  2186.   if (gb->Seconds)
  2187.   {
  2188.     x1 = gb->Width/2;
  2189.     x2 = x1+sinus[gb->Sec]*gb->Width2/300;
  2190.     y1 = gb->Height/2;
  2191.     y2 = y1-cosinus[gb->Sec]*gb->Height2/300;
  2192.  
  2193.     Move(rp,x1,y1);
  2194.     Draw(rp,x2,y2);
  2195.  
  2196.     if (gb->xDouble)
  2197.     { Move(rp,x1+1,y1);
  2198.       Draw(rp,x2+1,y2); }
  2199.  
  2200.     if (gb->yDouble)
  2201.     { Move(rp,x1,y1+1);
  2202.       Draw(rp,x2,y2+1); }
  2203.  
  2204.     if (x1 > x2)
  2205.     { tmp=x1; x1=x2; x2=tmp; }
  2206.     if (gb->xDouble)
  2207.       x2++;
  2208.     gb->ReDrawx1 = x1; gb->ReDrawx2 = x2;
  2209.  
  2210.     if (y1 > y2)
  2211.     { tmp=y1; y1=y2; y2=tmp; }
  2212.     if (gb->yDouble)
  2213.       y2++;
  2214.     gb->ReDrawy1 = y1; gb->ReDrawy2 = y2;
  2215.   }
  2216. }
  2217.  
  2218. /***************************************************************************/
  2219. /*                                                                         */
  2220. /* initialize background pattern mask                                      */
  2221. /*                                                                         */
  2222. /***************************************************************************/
  2223.  
  2224. VOID SetPattern()
  2225. { LONG i,a,b,c,d;
  2226.   UBYTE *p1;
  2227.   UWORD *p2;
  2228.  
  2229.   p1=&gb->Must[0]; a=*p1++; b=*p1++; c=*p1++; d=*p1;
  2230.  
  2231.   if (a==b && c==d) /* nur horizontale Streifen */
  2232.     gb->xMask = -1;
  2233.   else
  2234.     gb->xMask = -2;
  2235.  
  2236.   if (a==c && b==d) /* nur vertikale Streifen */
  2237.     gb->yMask = -1;
  2238.   else
  2239.     gb->yMask = -2;
  2240.  
  2241.   for (p2=&gb->Muster[0][0],i=0; i<8; i++)
  2242.   { *p2=(a&1<<i?0x5555:0)|(b&1<<i?0xaaaa:0); p2++;
  2243.     *p2=(c&1<<i?0x5555:0)|(d&1<<i?0xaaaa:0); p2++; }
  2244. }
  2245.  
  2246. /***************************************************************************/
  2247. /*                                                                         */
  2248. /* save current settings to the programs icon                              */
  2249. /*                                                                         */
  2250. /***************************************************************************/
  2251.  
  2252. enum {
  2253.   TT_TOP=0,TT_LEFT,TT_WIDTH,TT_HEIGHT,TT_SHOWFACE,TT_HANDTYPE,TT_HANDWIDTH,
  2254.   TT_BORDERTYPE,TT_WINDOWTYPE,TT_CHIME,TT_SECONDS,TT_OVAL,TT_SHADOW,
  2255.   TT_DRAWPENS,TT_PATTERN
  2256. };
  2257.  
  2258. CONST STRPTR ToolTypes[] = {
  2259.   "TOP","LEFT","WIDTH","HEIGHT","SHOWFACE","HANDTYPE","HANDWIDTH","BORDERTYPE",
  2260.   "WINDOWTYPE","CHIME","SECONDS","OVAL","SHADOW","DRAWPENS","PATTERN"
  2261. };
  2262.  
  2263. #define TTCOUNT (sizeof(ToolTypes)/sizeof(ToolTypes[0]))
  2264.  
  2265. VOID SaveSettings()
  2266. { struct DiskObject *dobj;
  2267.   BPTR old_cd;
  2268.  
  2269.   old_cd = CurrentDir(gb->ProgArg.wa_Lock);
  2270.  
  2271.   if ((dobj=GetDiskObjectNew(gb->ProgArg.wa_Name)) != NULL) /* Tooltypes einlesen */
  2272.   {
  2273.     UBYTE **tt,*t,*tbuf,*tbuf1;
  2274.     char **tmp,*p,**p1,**p2;
  2275.     LONG arg,i;
  2276.  
  2277.     p1=dobj->do_ToolTypes; p2=p1; do {} while(*p2++);
  2278.  
  2279.     if ((tbuf=AllocVec(((STRPTR)p2-(STRPTR)p1)+sizeof(ToolTypes)+40*TTCOUNT,MEMF_ANY)))
  2280.     {
  2281.       tt=(UBYTE **)(tbuf+40*TTCOUNT);
  2282.  
  2283.       p1=dobj->do_ToolTypes; p2=(char **)tt; do {} while((*p2++=*p1++));
  2284.  
  2285.       for (i=0;i<TTCOUNT;i++) /* eigene Tooltypes entfernen */
  2286.       { if (FindToolType(tt,t=GetToolType(i)))
  2287.         { p2=(char **)tt; do {} while(*++p2 && FindToolType((UBYTE **)p2,t));
  2288.           do { p=*p2++; } while((p2[-2]=p));
  2289.         }
  2290.       }
  2291.  
  2292.       /* Tooltypes zählen */
  2293.       p1=(char **)tt; do {} while(*p1++); --p1; tbuf1=tbuf;
  2294.  
  2295.       *p1++=tbuf1;
  2296.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_TOP,gb->MainWin->TopEdge);
  2297.  
  2298.       *p1++=tbuf1;
  2299.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_LEFT,gb->MainWin->LeftEdge);
  2300.  
  2301.       *p1++=tbuf1;
  2302.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_WIDTH,gb->Width);
  2303.  
  2304.       *p1++=tbuf1;
  2305.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HEIGHT,gb->Height);
  2306.  
  2307.       *p1++=tbuf1;
  2308.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_SHOWFACE,gb->Show);
  2309.  
  2310.       *p1++=tbuf1;
  2311.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HANDTYPE,gb->HandType);
  2312.  
  2313.       *p1++=tbuf1;
  2314.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_HANDWIDTH,gb->HandWidth);
  2315.  
  2316.       *p1++=tbuf1;
  2317.       arg = gb->BorderCount + (gb->HiRes ? 4 : 0) + (gb->Interlace ? 8 : 0);
  2318.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_BORDERTYPE,arg);
  2319.  
  2320.       *p1++=tbuf1;
  2321.       arg = (gb->CloseGad ? WT_CLOSEGAD : 0) + (gb->Backdrop ? WT_BACKDROP : 0) +
  2322.             (gb->Fixed ? WT_FIXED : 0) + (gb->UseImage ? WT_USEIMAGE : 0);
  2323.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_WINDOWTYPE,arg);
  2324.  
  2325.       *p1++=tbuf1;
  2326.       arg = gb->Chime + (gb->SmartHour ? 4 : 0);
  2327.       tbuf1=SetToolType(tbuf1,"%s=%ld",TT_CHIME,arg);
  2328.  
  2329.       if (gb->Seconds)
  2330.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_SECONDS); }
  2331.  
  2332.       if (gb->Oval)
  2333.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_OVAL); }
  2334.  
  2335.       if (gb->Shadow)
  2336.         { *p1++=tbuf1; tbuf1=SetToolType(tbuf1,"%s",TT_SHADOW); }
  2337.  
  2338.       *p1++=tbuf1;
  2339.       tbuf1=SetToolType(tbuf1,"%s=x",TT_DRAWPENS); tbuf1=SetStr(tbuf1,&gb->Pens[0],14);
  2340.  
  2341.       *p1++=tbuf1;
  2342.       tbuf1=SetToolType(tbuf1,"%s=x",TT_PATTERN); tbuf1=SetStr(tbuf1,&gb->Must[0],4);
  2343.  
  2344.       *p1=NULL;
  2345.  
  2346.       tmp=dobj->do_ToolTypes;
  2347.       dobj->do_ToolTypes=(char **)tt;
  2348.       PutDiskObject(gb->ProgArg.wa_Name,dobj);
  2349.       dobj->do_ToolTypes=tmp;
  2350.  
  2351.       FreeVec(tbuf);
  2352.     }
  2353.     FreeDiskObject(dobj);
  2354.   }
  2355.   CurrentDir(old_cd);
  2356. }
  2357.  
  2358. /*
  2359. ** make a tooltype string
  2360. */
  2361.  
  2362. CONST ULONG tricky=0x16c04e75; /* move.b d0,(a3)+ ; rts */
  2363.  
  2364. STRPTR SetToolType(STRPTR buf,STRPTR fmt,LONG num,...)
  2365. {
  2366.   ((STRPTR *)&num)[0] = GetToolType(num);
  2367.   RawDoFmt(fmt,(APTR)&num,(void (*)())&tricky,buf);
  2368.   return (buf+=strlen(buf)+1);
  2369. }
  2370.  
  2371. /*
  2372. ** get a tooltype name
  2373. */
  2374.  
  2375. STRPTR GetToolType(LONG num)
  2376. {
  2377.   return (STRPTR)ToolTypes[num];
  2378. }
  2379.  
  2380. /*
  2381. ** make an ascii pen-string
  2382. */
  2383.  
  2384. STRPTR SetStr(STRPTR dst,STRPTR src,LONG cnt)
  2385. {
  2386.   --dst;
  2387.   do
  2388.   { *dst++=DtoX(*src>>4);
  2389.     *dst++=DtoX(*src++&0xf);
  2390.   } while (--cnt);
  2391.   *dst++='\0'; return dst;
  2392. }
  2393.  
  2394. LONG DtoX(LONG a)
  2395. { if ((a+='0')>('9'))
  2396.     a+=7;
  2397.   return(a);
  2398. }
  2399.  
  2400. /***************************************************************************/
  2401. /*                                                                         */
  2402. /* audio stuff                                                             */
  2403. /*                                                                         */
  2404. /***************************************************************************/
  2405.  
  2406. CONST UWORD AlarmTune[] = {
  2407.   800,800,800,800,800,800,800,1600,
  2408.   800,800,800,800,800,800,800,1600,
  2409.   800,800,800,800,800,800,800,1600,
  2410.   800,800,800,800,800,800,800,1600,
  2411.   800,800,800,800,800,800,800,4,0
  2412. };
  2413.  
  2414. CONST UWORD HourTune[] = {
  2415.   800,1600,800,1600,800,1600,800,1600,
  2416.   800,1600,800,1600,800,1600,800,1600,
  2417.   800,1600,800,1600,800,1600,800,4,0
  2418. };
  2419.  
  2420. CONST UWORD QuarterTune[] = {
  2421.   400,400,400,400,400,4,0
  2422. };
  2423.  
  2424. VOID TestIfAlarm()
  2425. { CONST UWORD *tune;
  2426.   ULONG st2;
  2427.   LONG mi2,i;
  2428.  
  2429.   st2=gb->Std; mi2 = gb->Min;
  2430.   if (!(st2/=5))
  2431.     st2=12;
  2432.   tune = AlarmTune;
  2433.   if (!gb->Alarm || mi2!=gb->AlMin || st2!=gb->AlStd)
  2434.   { if (!gb->Chime)
  2435.       return;
  2436.     if (!mi2)
  2437.     {
  2438.       tune = HourTune; i=22; if (gb->SmartHour) i=24-st2;
  2439.     }
  2440.     else
  2441.     { if (gb->Chime != 2)
  2442.         return;
  2443.       tune = QuarterTune;
  2444.       for(i=6;;)
  2445.        { i-=2;
  2446.          if ((mi2-=15)<0)
  2447.            return;
  2448.          if (mi2==0)
  2449.            break;
  2450.        }
  2451.     }
  2452.     tune = &tune[i];
  2453.   }
  2454.   StartTune(tune);
  2455. }
  2456.  
  2457. /*
  2458. ** allocate audio channels and initiate the sound
  2459. */
  2460.  
  2461. CONST UBYTE ChannelMap[] = { 1,2,4,8 }; /* Sound Channel Allocation Map */
  2462.  
  2463. VOID StartTune(CONST UWORD *tune)
  2464. { struct IOAudio *io;
  2465.  
  2466.   if (!gb->SoundOn)
  2467.   {
  2468.     io = gb->AudioIO[0];
  2469.     io->ioa_Request.io_Command = ADCMD_ALLOCATE;
  2470.     io->ioa_Request.io_Message.mn_Node.ln_Pri = 90; /* ALARM-Level */
  2471.     io->ioa_Request.io_Flags   = ADIOF_NOWAIT;
  2472.     io->ioa_Data               = (UBYTE *)&ChannelMap[0];
  2473.     io->ioa_Length             = sizeof(ChannelMap);
  2474.     BeginIO(&io->ioa_Request);
  2475.     if (!WaitIO(&io->ioa_Request))
  2476.     {
  2477.       gb->SoundOn = -1;
  2478.       if (!(ciaa.ciapra & CIAF_LED))
  2479.       {
  2480.         ciaa.ciapra |= CIAF_LED; gb->Filter = -1;
  2481.       }
  2482.       CopyMemQuick(io,gb->AudioIO[1],sizeof(struct IOAudio));
  2483.       gb->PlayTune = (UWORD *)tune;
  2484.       PlayNote();
  2485.       PlayNote();
  2486.     }
  2487.   }
  2488. }
  2489.  
  2490. /*
  2491. ** beep, beep, ...
  2492. */
  2493.  
  2494. VOID PlayNote()
  2495. { struct IOAudio *io;
  2496.   LONG old,new;
  2497.   BYTE *sent = &gb->AudioSent[0];
  2498.  
  2499.   old = gb->RequestNr;
  2500.   new = !old;
  2501.   gb->RequestNr = new;
  2502.  
  2503.   sent[old] =  0;
  2504.   if (!*gb->PlayTune)
  2505.   { if (!sent[new]) /* Anderer Request auch zurück ? */
  2506.       EndTune(); return; }
  2507.   sent[old] = -1;   /* Merken */
  2508.   io = gb->AudioIO[old];
  2509.   io->ioa_Request.io_Command = CMD_WRITE;
  2510.   io->ioa_Request.io_Flags   = ADIOF_PERVOL;
  2511.   io->ioa_Data               = (UBYTE *)&((ULONG *)gb->WaveForm)[old];
  2512.   io->ioa_Length             = 4;
  2513.   io->ioa_Period             = 500; /* ekliger Piepton */
  2514.   io->ioa_Volume             = 64;
  2515.   io->ioa_Cycles             = *(gb->PlayTune)++;
  2516.   BeginIO(&io->ioa_Request);
  2517. }
  2518.  
  2519. /*
  2520. ** end audio output
  2521. */
  2522.  
  2523. VOID EndTune()
  2524. { struct IOAudio *io = gb->AudioIO[0];
  2525.  
  2526.   io->ioa_Request.io_Command=ADCMD_FREE;
  2527.   DoIO(&io->ioa_Request);
  2528.   if (gb->Filter)
  2529.   {
  2530.     ciaa.ciapra &= ~CIAF_LED; gb->Filter = 0;
  2531.   }
  2532.   gb->SoundOn = 0;
  2533. }
  2534.  
  2535. /***************************************************************************/
  2536. /*                                                                         */
  2537. /* create a new window and its gadgets                                     */
  2538. /*                                                                         */
  2539. /***************************************************************************/
  2540.  
  2541. CONST struct TextAttr Topaz = {
  2542.   "topaz.font",8,FS_NORMAL,FPF_ROMFONT
  2543. };
  2544.  
  2545. VOID CreateRequest(struct WinGad *wg,struct wInfo *wi,struct TagItem **tagptr)
  2546. { struct Gadget *context;
  2547.  
  2548.   if ((context=CreateContext(&wg->Gad)) != NULL)
  2549.   {
  2550.     struct NewWindow *nw = &gb->NewWindowBuf;
  2551.     struct Window *win;
  2552.     struct gInfo *gi;
  2553.     UWORD cnt;
  2554.  
  2555.     nw->LeftEdge    = 100;
  2556.     nw->TopEdge     = 100;
  2557.     nw->Width       = 0;
  2558.     nw->Height      = 0;
  2559.     nw->Flags       = WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_ACTIVATE|WFLG_RMBTRAP;
  2560.     nw->FirstGadget = wg->Gad;
  2561.     nw->Title       = GetCatalogString(wi->textnr);
  2562.  
  2563.     gb->NewGad.ng_GadgetID = 0; cnt = wi->gadcnt; gi = &wi->gi[0];
  2564.     do
  2565.     { struct NewGadget *ng = &gb->NewGad;
  2566.       struct Screen *scr = nw->Screen;
  2567.       ULONG num;
  2568.  
  2569.       ng->ng_LeftEdge   = gi->left + scr->WBorLeft;
  2570.       ng->ng_TopEdge    = gi->top  + scr->WBorLeft + scr->RastPort.TxHeight;
  2571.       ng->ng_Width      = gi->width;
  2572.       ng->ng_Height     = gi->height;
  2573.       if ((num=gi->textnr))
  2574.         num = (ULONG)GetCatalogString(num);
  2575.       ng->ng_GadgetText = (STRPTR)num;
  2576.       ng->ng_TextAttr   = (struct TextAttr *)&Topaz;
  2577.       ng->ng_GadgetID++;
  2578.       ng->ng_VisualInfo = gb->VisualInfo;
  2579.  
  2580.       if ((context=CreateGadgetA(gi->kind,context,ng,tagptr[0])) == NULL)
  2581.       {
  2582.         FreeGadgets(wg->Gad); wg->Gad = NULL; return;
  2583.       }
  2584.  
  2585.       gi++; tagptr++;
  2586.     } while(--cnt);
  2587.  
  2588.     if ((wg->Win=(win=OpenWindowShared(&gb->NewWindowBuf,&WindowTags[0],wi->idcmp))) != NULL)
  2589.     {
  2590.       SetWindowTitles(win,(UBYTE *)-1L,PROGNAME); GT_RefreshWindow(win,NULL);
  2591.     }
  2592.     else
  2593.     {
  2594.       FreeGadgets(wg->Gad); wg->Gad = NULL;
  2595.     }
  2596.   }
  2597. }
  2598.  
  2599. /***************************************************************************/
  2600. /*                                                                         */
  2601. /* open a window for shared IDCMP                                          */
  2602. /*                                                                         */
  2603. /***************************************************************************/
  2604.  
  2605. struct Window *OpenWindowShared(struct NewWindow *nw,CONST struct TagItem *tl,ULONG idcmp)
  2606. { struct Window *win;
  2607.  
  2608.   if ((win=OpenWindowTagList(nw,(struct TagItem *)tl)) != NULL)
  2609.   {
  2610.     win->UserPort = gb->WindowPort;
  2611.     if (!ModifyIDCMP(win,idcmp))
  2612.     {
  2613.       CloseWindowSafely(win); win=NULL;
  2614.     }
  2615.   }
  2616.   return win;
  2617. }
  2618.  
  2619. /***************************************************************************/
  2620. /*                                                                         */
  2621. /* get localized string                                                    */
  2622. /*                                                                         */
  2623. /***************************************************************************/
  2624.  
  2625. CONST STRPTR LocStrings[] = {
  2626.   /* MSG_PROJECT     */ "Project",
  2627.   /* MSG_ABOUT       */ "About",
  2628.   /* MSG_ABOUTKEY    */ "?",
  2629.   /* MSG_QUIT        */ "Quit",
  2630.   /* MSG_QUITKEY     */ "Q",
  2631.   /* MSG_SETTINGS    */ "Settings",
  2632.   /* MSG_SECONDS     */ "Seconds",
  2633.   /* MSG_OVAL        */ "Oval",
  2634.   /* MSG_SHOW        */ "Show",
  2635.   /* MSG_MINUTES     */ "Minutes",
  2636.   /* MSG_HOURS       */ "Hours",
  2637.   /* MSG_QUARTER     */ "Quarter",
  2638.   /* MSG_ONE         */ "One",
  2639.   /* MSG_NONE        */ "None",
  2640.   /* MSG_HANDS       */ "Hands",
  2641.   /* MSG_LINE        */ "Line",
  2642.   /* MSG_TRIANGLE    */ "Triangle",
  2643.   /* MSG_RHOMBUS     */ "Rhombus",
  2644.   /* MSG_RECTANGLE   */ "Rectangle",
  2645.   /* MSG_VERYTHIN    */ "Very Thin",
  2646.   /* MSG_THIN        */ "Thin",
  2647.   /* MSG_NORMAL      */ "Normal",
  2648.   /* MSG_THICK       */ "Thick",
  2649.   /* MSG_VERYTHICK   */ "Very Thick",
  2650.   /* MSG_SHADOW      */ "Shadow",
  2651.   /* MSG_BORDER      */ "Border",
  2652.   /* MSG_SINGLE      */ "Single",
  2653.   /* MSG_DOUBLE      */ "Double",
  2654.   /* MSG_HIRES       */ "HiRes",
  2655.   /* MSG_INTERLACE   */ "Interlace",
  2656.   /* MSG_CHIME       */ "Chime",
  2657.   /* MSG_SMART       */ "Smart",
  2658.   /* MSG_ALARM       */ "Alarm",
  2659.   /* MSG_SET         */ "Set",
  2660.   /* MSG_ON          */ "On",
  2661.   /* MSG_USEIMAGE    */ "Use Image",
  2662.   /* MSG_CLOSEGAD    */ "Close Gadget",
  2663.   /* MSG_SAVESETTING */ "Save Settings",
  2664.   /* MSG_SAVEKEY     */ "S",
  2665.   /* MSG_COLORS      */ "Colors",
  2666.   /* MSG_MINAPEN     */ "Min. APen",
  2667.   /* MSG_MINOPEN     */ "Min. OPen",
  2668.   /* MSG_HOURAPEN    */ "Hour Apen",
  2669.   /* MSG_HOUROPEN    */ "Hour Open",
  2670.   /* MSG_STR12       */ "12",
  2671.   /* MSG_BORDER0     */ "Border 0",
  2672.   /* MSG_BORDER1     */ "Border 1",
  2673.   /* MSG_BORDER2     */ "Border 2",
  2674.   /* MSG_BORDER3     */ "Border 3",
  2675.   /* MSG_PATTERN     */ "Pattern",
  2676.   /* MSG_COLOR0      */ "Color 0",
  2677.   /* MSG_COLOR1      */ "Color 1",
  2678.   /* MSG_COLOR2      */ "Color 2",
  2679.   /* MSG_COLOR3      */ "Color 3",
  2680.   /* MSG_DESCRIPTION */ "a really nice clock !",
  2681.   /* MSG_CHOOSE      */ "Choose one:",
  2682.   /* MSG_USE         */ "Use",
  2683.   /* MSG_CANCEL      */ "Cancel",
  2684.   /*
  2685.   ** new with 1.5
  2686.   */
  2687.   /* MSG_WINDOW      */ "Window",
  2688.   /* MSG_BACKDROP    */ "Backdrop",
  2689.   /* MSG_FIXED       */ "Immovable"
  2690. };
  2691.  
  2692. STRPTR GetCatalogString(LONG strnum)
  2693. { struct Catalog *cat;
  2694.   STRPTR loc;
  2695.  
  2696.   loc = LocStrings[strnum];
  2697.   if ((cat=gb->Catalog) != NULL)
  2698.     loc = GetCatalogStr(cat,strnum,loc);
  2699.   return loc;
  2700. }
  2701.  
  2702. /***************************************************************************/
  2703. /*                                                                         */
  2704. /* duplicate a bitmap (based on the work of P.Carette + W.Dörwald)         */
  2705. /*                                                                         */
  2706. /***************************************************************************/
  2707.  
  2708. VOID CopyTiledBitMap(struct BitMap *Src,LONG SrcSizeX,LONG SrcSizeY,struct BitMap *Dst,LONG DstSizeX,LONG DstSizeY)
  2709. { LONG Pos;  /* used as starting position in the "exponential" blit */
  2710.   LONG Size; /* used as bitmap size in the "exponential" blit       */
  2711.  
  2712.   /* blit the first piece of the tile */
  2713.   blt_bitmap(Src,0,0,Dst,0,0,MIN(SrcSizeX,DstSizeX),MIN(SrcSizeY,DstSizeY),0xC0,-1,NULL);
  2714.  
  2715.   /* this loop generates the first row of the tiles */
  2716.   for (Pos = SrcSizeX,Size = MIN(SrcSizeX,DstSizeX-Pos);Pos<DstSizeX;)
  2717.   {
  2718.     blt_bitmap(Dst,0,0,Dst,Pos,0,Size,MIN(SrcSizeY,DstSizeY),0xC0,-1,NULL);
  2719.     Pos += Size;
  2720.     Size = MIN(Size<<1,DstSizeX-Pos);
  2721.   }
  2722.  
  2723.   /* this loop blit the first row down several times to fill the whole dest rect */
  2724.   for (Pos = SrcSizeY,Size = MIN(SrcSizeY,DstSizeY-Pos);Pos<DstSizeY;)
  2725.   {
  2726.     blt_bitmap(Dst,0,0,Dst,0,Pos,DstSizeX,Size,0xC0,-1,NULL);
  2727.     Pos += Size;
  2728.     Size = MIN(Size<<1,DstSizeY-Pos);
  2729.   }
  2730. }
  2731.  
  2732. /***************************************************************************/
  2733. /*                                                                         */
  2734. /* replacement functions                                                   */
  2735. /*                                                                         */
  2736. /***************************************************************************/
  2737.  
  2738. LONG blt_bitmap(struct BitMap *src,LONG xsrc,LONG ysrc,struct BitMap *dst,
  2739.                 LONG xdst,LONG ydst,LONG xsize,LONG ysize,ULONG minterm,
  2740.                 ULONG mask,PLANEPTR tempA)
  2741. {
  2742.   return BltBitMap(src,xsrc,ysrc,dst,xdst,ydst,xsize,ysize,minterm,mask,tempA);
  2743. }
  2744.  
  2745. Object *new_dt_object(APTR name,ULONG data,...)
  2746. {
  2747.   return NewDTObjectA(name,(struct TagItem *)&data);
  2748. }
  2749.  
  2750. ULONG get_dt_attrs(Object *obj,ULONG data,...)
  2751. {
  2752.   return GetDTAttrsA(obj,(struct TagItem *)&data);
  2753. }
  2754.  
  2755. /***************************************************************************/
  2756. /*                                                                         */
  2757. /* The End                                                                 */
  2758. /*                                                                         */
  2759. /***************************************************************************/
  2760.